#!/usr/bin/env bash # # hubspoke-helper.sh - Manage hub/spoke rclone mounts # Assumes spoke Docker files exist in ~/autossh-tunnel/ # Simplified hub mount uses direct rclone commands (no systemd services) set -euo pipefail # ------------------------------------------------------------ # Configuration (override with env vars if needed) # ------------------------------------------------------------ TUNNEL_DIR="${TUNNEL_DIR:-$HOME/tinyboard/spoke}" COMPOSE_FILE="${COMPOSE_FILE:-$TUNNEL_DIR/compose.yaml}" RCLONE_REMOTE="${RCLONE_REMOTE:-brie-remote}" MOUNT_POINT="${MOUNT_POINT:-$/mnt/hub/$RCLONE_REMOTE}" # ------------------------------------------------------------ # Usage # ------------------------------------------------------------ usage() { cat <&2 exit 1 } # ------------------------------------------------------------ # Spoke actions (docker) # ------------------------------------------------------------ spoke_build() { if [ ! -f "$COMPOSE_FILE" ]; then die "docker-compose.yaml not found at $COMPOSE_FILE" fi cd "$TUNNEL_DIR" docker build --build-arg UID=$(id -u armbian) --build-arg GID=$(id -g armbian) -t spoke-autossh . echo "Image built. Use '$0 spoke start' to run." } spoke_start() { cd "$TUNNEL_DIR" docker-compose up -d } spoke_stop() { cd "$TUNNEL_DIR" docker-compose down } spoke_restart() { cd "$TUNNEL_DIR" docker-compose restart } spoke_status() { docker ps --filter name=spoke-autossh --format "table {{.Names}}\t{{.Status}}" } spoke_logs() { cd "$TUNNEL_DIR" docker-compose logs --tail=50 -f } spoke_show_cmd() { cat </dev/null 2>&1 & echo "Mount started in background (PID: $!)" echo "Check status with: $0 hub status" } hub_start_background() { # Internal function for crontab/auto-start mkdir -p "$MOUNT_POINT" rclone mount "${RCLONE_REMOTE}:" "$MOUNT_POINT" \ --config "${HOME}/.config/rclone/rclone.conf" \ --vfs-cache-mode writes \ --allow-other \ --daemon } hub_stop() { echo "Stopping rclone mount..." if hub_unmount; then echo "Mount stopped." else echo "Could not unmount. Trying force unmount..." fusermount -uz "$MOUNT_POINT" 2>/dev/null && echo "Force unmounted." || echo "Still could not unmount." fi } hub_status() { if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then echo "Mount point $MOUNT_POINT is mounted." mount | grep "$MOUNT_POINT" else echo "Mount point $MOUNT_POINT is NOT mounted." echo "Check if rclone process is running:" pgrep -af rclone || echo "No rclone mount processes found." fi } hub_mount() { mkdir -p "$MOUNT_POINT" echo "Mounting in foreground. Press Ctrl+C to unmount." rclone mount "${RCLONE_REMOTE}:" "$MOUNT_POINT" \ --config "${HOME}/.config/rclone/rclone.conf" \ --vfs-cache-mode writes \ --allow-other } hub_unmount() { fusermount -u "$MOUNT_POINT" 2>/dev/null && echo "Unmounted." || echo "Not mounted." } # ------------------------------------------------------------ # Dispatch # ------------------------------------------------------------ if [ $# -lt 2 ]; then usage exit 1 fi ROLE="$1" ACTION="$2" case "$ROLE" in spoke) case "$ACTION" in build) spoke_build ;; start) spoke_start ;; stop) spoke_stop ;; restart) spoke_restart ;; status) spoke_status ;; logs) spoke_logs ;; show-cmd) spoke_show_cmd ;; *) die "Unknown action for spoke: $ACTION" ;; esac ;; hub) case "$ACTION" in install) hub_install ;; start) hub_start ;; start-background) hub_start_background ;; stop) hub_stop ;; status) hub_status ;; mount) hub_mount ;; unmount) hub_unmount ;; *) die "Unknown action for hub: $ACTION" ;; esac ;; *) usage exit 1 ;; esac