forked from finn/tinyboard
first pass helper script
This commit is contained in:
200
hubspoke-helper.sh
Executable file
200
hubspoke-helper.sh
Executable file
@@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# hubspoke-helper.sh - Manage hub/spoke rclone mounts over reverse SSH
|
||||
#
|
||||
# This script helps configure and control the two sides:
|
||||
# - Spoke: establishes a reverse SSH tunnel (autossh)
|
||||
# - Hub: mounts the spoke's filesystem via rclone/sftp
|
||||
#
|
||||
# It expects service template files in:
|
||||
# ./spoke/autossh-tunnel.service
|
||||
# ./hub/rclone-mount@.service
|
||||
#
|
||||
# Those files can be copied or piped into place by this script.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Configuration (adjust these to your environment)
|
||||
# ------------------------------------------------------------
|
||||
SPOKE_AUTOSSH_SERVICE_SRC="./spoke/autossh-tunnel.service"
|
||||
HUB_RCLONE_SERVICE_SRC="./hub/rclone-mount@.service"
|
||||
|
||||
# Default values (can be overridden with environment variables or interactive prompts)
|
||||
HUB_USER="${HUB_USER:-armbian}"
|
||||
HUB_HOST="${HUB_HOST:-oily.dad}"
|
||||
SPOKE_USER="${SPOKE_USER:-armbian}"
|
||||
TUNNEL_PORT="${TUNNEL_PORT:-11111}"
|
||||
SPOKE_SSH_KEY="${SPOKE_SSH_KEY:-$HOME/.ssh/armbian-brie-202604}"
|
||||
RCLONE_REMOTE_NAME="${RCLONE_REMOTE_NAME:-brie-remote}"
|
||||
MOUNT_POINT="${MOUNT_POINT:-$HOME/mnt/brie}"
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Helper functions
|
||||
# ------------------------------------------------------------
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 {hub|spoke} {action}
|
||||
|
||||
Manage hub/spoke rclone setup.
|
||||
|
||||
ACTIONS FOR SPOKE:
|
||||
show-cmd Show the autossh command to run manually
|
||||
install Install the autossh system service (requires sudo)
|
||||
start Start the installed service (requires sudo)
|
||||
stop Stop the installed service (requires sudo)
|
||||
status Show status of the autossh service
|
||||
|
||||
ACTIONS FOR HUB:
|
||||
show-cmd Show the manual rclone mount command
|
||||
install Install the rclone user service (no sudo)
|
||||
start Start the rclone user service
|
||||
stop Stop the rclone user service
|
||||
status Show status of the rclone user service
|
||||
mount Manual foreground mount (for testing)
|
||||
unmount Unmount manually (fusermount -u)
|
||||
|
||||
EXAMPLES:
|
||||
$0 spoke show-cmd
|
||||
$0 spoke install
|
||||
$0 hub install
|
||||
$0 hub start
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "ERROR: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
check_service_file() {
|
||||
local file="$1"
|
||||
if [ ! -f "$file" ]; then
|
||||
die "Service template not found: $file"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Spoke actions
|
||||
# ------------------------------------------------------------
|
||||
spoke_show_cmd() {
|
||||
cat <<EOF
|
||||
Run this command manually on the SPOKE to establish the reverse tunnel:
|
||||
autossh -M 0 -NT -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" \\
|
||||
-R ${TUNNEL_PORT}:localhost:22 -i ${SPOKE_SSH_KEY} ${HUB_USER}@${HUB_HOST}
|
||||
EOF
|
||||
}
|
||||
|
||||
spoke_install() {
|
||||
check_service_file "$SPOKE_AUTOSSH_SERVICE_SRC"
|
||||
echo "Installing autossh system service on SPOKE..."
|
||||
sudo cp "$SPOKE_AUTOSSH_SERVICE_SRC" /etc/systemd/system/autossh-tunnel.service
|
||||
sudo systemctl daemon-reload
|
||||
echo "Service installed. Enable with: sudo systemctl enable autossh-tunnel.service"
|
||||
echo "Start with: sudo systemctl start autossh-tunnel.service"
|
||||
}
|
||||
|
||||
spoke_start() {
|
||||
sudo systemctl start autossh-tunnel.service
|
||||
echo "Started."
|
||||
}
|
||||
|
||||
spoke_stop() {
|
||||
sudo systemctl stop autossh-tunnel.service
|
||||
echo "Stopped."
|
||||
}
|
||||
|
||||
spoke_status() {
|
||||
sudo systemctl status autossh-tunnel.service --no-pager
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Hub actions
|
||||
# ------------------------------------------------------------
|
||||
hub_show_cmd() {
|
||||
cat <<EOF
|
||||
Manual rclone mount command on HUB (run in foreground, Ctrl+C to stop):
|
||||
mkdir -p ${MOUNT_POINT}
|
||||
rclone mount ${RCLONE_REMOTE_NAME}: ${MOUNT_POINT} \\
|
||||
--config ${HOME}/.config/rclone/rclone.conf \\
|
||||
--vfs-cache-mode writes \\
|
||||
--allow-other
|
||||
EOF
|
||||
}
|
||||
|
||||
hub_install() {
|
||||
check_service_file "$HUB_RCLONE_SERVICE_SRC"
|
||||
echo "Installing rclone user service on HUB..."
|
||||
mkdir -p "$HOME/.config/systemd/user"
|
||||
cp "$HUB_RCLONE_SERVICE_SRC" "$HOME/.config/systemd/user/rclone-mount@.service"
|
||||
systemctl --user daemon-reload
|
||||
echo "Service installed. Enable with: systemctl --user enable rclone-mount@${RCLONE_REMOTE_NAME}.service"
|
||||
echo "Start with: systemctl --user start rclone-mount@${RCLONE_REMOTE_NAME}.service"
|
||||
}
|
||||
|
||||
hub_start() {
|
||||
systemctl --user start "rclone-mount@${RCLONE_REMOTE_NAME}.service"
|
||||
echo "Started."
|
||||
}
|
||||
|
||||
hub_stop() {
|
||||
systemctl --user stop "rclone-mount@${RCLONE_REMOTE_NAME}.service"
|
||||
echo "Stopped."
|
||||
}
|
||||
|
||||
hub_status() {
|
||||
systemctl --user status "rclone-mount@${RCLONE_REMOTE_NAME}.service" --no-pager
|
||||
}
|
||||
|
||||
hub_mount() {
|
||||
mkdir -p "$MOUNT_POINT"
|
||||
echo "Mounting in foreground. Press Ctrl+C to unmount."
|
||||
rclone mount "${RCLONE_REMOTE_NAME}:" "$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 or already unmounted."
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Main dispatch
|
||||
# ------------------------------------------------------------
|
||||
if [ $# -lt 2 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROLE="$1"
|
||||
ACTION="$2"
|
||||
|
||||
case "$ROLE" in
|
||||
spoke)
|
||||
case "$ACTION" in
|
||||
show-cmd) spoke_show_cmd ;;
|
||||
install) spoke_install ;;
|
||||
start) spoke_start ;;
|
||||
stop) spoke_stop ;;
|
||||
status) spoke_status ;;
|
||||
*) die "Unknown action for spoke: $ACTION" ;;
|
||||
esac
|
||||
;;
|
||||
hub)
|
||||
case "$ACTION" in
|
||||
show-cmd) hub_show_cmd ;;
|
||||
install) hub_install ;;
|
||||
start) hub_start ;;
|
||||
stop) hub_stop ;;
|
||||
status) hub_status ;;
|
||||
mount) hub_mount ;;
|
||||
unmount) hub_unmount ;;
|
||||
*) die "Unknown action for hub: $ACTION" ;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user