Compare commits

..

11 Commits

Author SHA1 Message Date
62e1629db6 prepare for second tunnel 2026-04-16 00:32:37 +00:00
eba72013b9 further fix readme 2026-04-15 12:33:51 -07:00
08328c77e7 doc cleanup 2026-04-15 12:01:09 -07:00
c122007a46 fix typo 2026-04-14 19:07:09 -07:00
de05ffdb7d annoying typo 2026-04-14 18:43:09 -07:00
b7b3a9beaa fix container sftp2 2026-04-14 16:40:21 -07:00
14079d889b fix container sftp 2026-04-14 16:36:11 -07:00
5f5d2fa760 add syncthing to spoke 2026-04-14 15:29:25 -07:00
d7014588f6 fix inline help 2026-04-14 15:21:49 -07:00
b16826fa8e change mountpoint 2026-04-13 23:31:40 -07:00
56dff3f22b no user systemd it's stupid 2026-04-13 14:04:48 -07:00
7 changed files with 106 additions and 97 deletions

View File

@@ -28,12 +28,10 @@ This system implements a hub-and-spoke model where:
tinyboard/ tinyboard/
├── hubspoke-helper.sh # Main management script ├── hubspoke-helper.sh # Main management script
├── hub/ ├── hub/
│ ├── rclone-mount@.service # Systemd user service template
│ └── rclone.conf # Rclone SFTP configuration │ └── rclone.conf # Rclone SFTP configuration
├── spoke/ ├── spoke/
│ ├── compose.yaml # Docker Compose for autossh tunnel │ ├── compose.yaml # Docker Compose for autossh tunnel
│ ├── Dockerfile # autossh container image │ ├── Dockerfile # autossh container image
│ ├── autossh-tunnel.service # Legacy systemd service (deprecated)
│ ├── autohostname.sh # Hostname assignment by MAC address │ ├── autohostname.sh # Hostname assignment by MAC address
│ ├── aptprimary.sh # Initial package installation │ ├── aptprimary.sh # Initial package installation
│ ├── clean_sensitive.sh # Clean WiFi/password from configs │ ├── clean_sensitive.sh # Clean WiFi/password from configs
@@ -54,6 +52,7 @@ tinyboard/
- `~/.config/rclone/rclone.conf` on hub must be manually created - `~/.config/rclone/rclone.conf` on hub must be manually created
- Use `hub/rclone.conf` as a template - Use `hub/rclone.conf` as a template
- Update host, port, and key_file paths as needed - Update host, port, and key_file paths as needed
- Manually create rclone mount and permission it (`/mnt/hub` for example)
### Systemd Service Files ### Systemd Service Files
- `~/.config/systemd/user/rclone-mount@.service` must be manually copied from `hub/rclone-mount@.service` - `~/.config/systemd/user/rclone-mount@.service` must be manually copied from `hub/rclone-mount@.service`
@@ -62,9 +61,9 @@ tinyboard/
### Initial Setup ### Initial Setup
1. Write Armbian minimal image to SD card 1. Write Armbian minimal image to SD card
2. Copy `spoke/armb-not_logged_in_yet` to SD card root (contains WiFi credentials) 2. Copy `spoke/armb-not_logged_in_yet` to SD card root `/root/.not_logged_in_yet` (contains WiFi credentials)
3. Boot device, SSH in as root with password "1234" 3. Boot device, SSH in as root with password "1234"
4. After first login, `armb-not_logged_in_yet` will be processed for root and armbian user credentials 4. After first login and setup tasks, `.not_logged_in_yet` will be processed for root and armbian user credentials
5. Clone this repository: `git clone <repo-url>` 5. Clone this repository: `git clone <repo-url>`
6. Run `spoke/aptprimary.sh` to install required packages 6. Run `spoke/aptprimary.sh` to install required packages
7. Run `spoke/autohostname.sh` to assign hostname based on MAC address 7. Run `spoke/autohostname.sh` to assign hostname based on MAC address
@@ -99,12 +98,6 @@ tinyboard/
3. Copy and customize `hub/rclone.conf` to `~/.config/rclone/rclone.conf` 3. Copy and customize `hub/rclone.conf` to `~/.config/rclone/rclone.conf`
4. Update key_file path to point to your SSH private key 4. Update key_file path to point to your SSH private key
### Systemd Service Setup
1. Create user systemd directory: `mkdir -p ~/.config/systemd/user`
2. Copy `hub/rclone-mount@.service` to `~/.config/systemd/user/`
3. Enable lingering for user services: `sudo loginctl enable-linger $USER`
4. Reload systemd: `systemctl --user daemon-reload`
### FUSE Configuration ### FUSE Configuration
```bash ```bash
# Allow other users to access mounts (if needed) # Allow other users to access mounts (if needed)
@@ -118,6 +111,10 @@ sudo usermod -aG fuse $USER
## Usage ## Usage
### Managing Spoke Tunnels ### Managing Spoke Tunnels
- Docker on spoke should handle autostart of spoke tunnel
- Syncthing can be combined in this image
- Rename syncthing image and host names per-device in the compose file.
```bash ```bash
# Build autossh container # Build autossh container
./hubspoke-helper.sh spoke build ./hubspoke-helper.sh spoke build
@@ -136,6 +133,13 @@ sudo usermod -aG fuse $USER
``` ```
### Managing Hub Mounts ### Managing Hub Mounts
#### Crontab entry:
```
@reboot /home/armbian/tinyboard/hubspoke-helper.sh hub start-background
```
#### Deprecated: systemd
```bash ```bash
# Install systemd service (after manual file placement) # Install systemd service (after manual file placement)
./hubspoke-helper.sh hub install ./hubspoke-helper.sh hub install
@@ -158,7 +162,7 @@ Environment variables can override defaults:
- `TUNNEL_DIR`: Directory containing spoke Docker files (default: `~/tinyboard/spoke`) - `TUNNEL_DIR`: Directory containing spoke Docker files (default: `~/tinyboard/spoke`)
- `COMPOSE_FILE`: Docker compose file path (default: `$TUNNEL_DIR/compose.yaml`) - `COMPOSE_FILE`: Docker compose file path (default: `$TUNNEL_DIR/compose.yaml`)
- `RCLONE_REMOTE`: Rclone remote name (default: `brie-remote`) - `RCLONE_REMOTE`: Rclone remote name (default: `brie-remote`)
- `MOUNT_POINT`: Mount point on hub (default: `~/mnt/brie`) - `MOUNT_POINT`: Mount point on hub (default: `~/mnt/hub`)
## Security Notes ## Security Notes

View File

@@ -1,25 +0,0 @@
#~/.config/systemd/user/rclone-mount@.service
[Unit]
Description=Rclone mount of %i
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStartPre=/usr/bin/mkdir -p %h/mnt/%i
ExecStart=/usr/bin/rclone mount %i: %h/mnt/%i \
--config=%h/.config/rclone/rclone.conf \
--vfs-cache-mode writes \
--vfs-cache-max-size 256M \
--allow-other \
--log-level INFO \
--log-file %h/.local/share/rclone-%i.log
ExecStop=/bin/fusermount -u %h/mnt/%i
Restart=on-failure
RestartSec=10
StartLimitInterval=60
StartLimitBurst=3
[Install]
WantedBy=default.target

View File

@@ -7,3 +7,12 @@ shell_type = unix
md5sum_command = md5sum md5sum_command = md5sum
sha1sum_command = sha1sum sha1sum_command = sha1sum
#[new-remote]
#type = sftp
#host = localhost
#port = 11112
#key_file = /home/armbian/.ssh/a new priv key for tunnel back to new spoke
#shell_type = unix
#md5sum_command = md5sum
#sha1sum_command = sha1sum

View File

@@ -2,7 +2,7 @@
# #
# hubspoke-helper.sh - Manage hub/spoke rclone mounts # hubspoke-helper.sh - Manage hub/spoke rclone mounts
# Assumes spoke Docker files exist in ~/autossh-tunnel/ # Assumes spoke Docker files exist in ~/autossh-tunnel/
# Assumes hub rclone service template is manually placed (or not needed) # Simplified hub mount uses direct rclone commands (no systemd services)
set -euo pipefail set -euo pipefail
@@ -12,7 +12,7 @@ set -euo pipefail
TUNNEL_DIR="${TUNNEL_DIR:-$HOME/tinyboard/spoke}" TUNNEL_DIR="${TUNNEL_DIR:-$HOME/tinyboard/spoke}"
COMPOSE_FILE="${COMPOSE_FILE:-$TUNNEL_DIR/compose.yaml}" COMPOSE_FILE="${COMPOSE_FILE:-$TUNNEL_DIR/compose.yaml}"
RCLONE_REMOTE="${RCLONE_REMOTE:-brie-remote}" RCLONE_REMOTE="${RCLONE_REMOTE:-brie-remote}"
MOUNT_POINT="${MOUNT_POINT:-$HOME/mnt/$RCLONE_REMOTE}" MOUNT_POINT="${MOUNT_POINT:-/mnt/hub/$RCLONE_REMOTE}"
# ------------------------------------------------------------ # ------------------------------------------------------------
# Usage # Usage
@@ -30,11 +30,12 @@ SPOKE ACTIONS (docker-based, no systemd):
logs Show container logs logs Show container logs
show-cmd Show manual autossh command (non-docker) show-cmd Show manual autossh command (non-docker)
HUB ACTIONS (systemd user service for rclone mount): HUB ACTIONS (simplified rclone mount - no systemd):
install Install the rclone user service (needs service file) install Show simplified setup instructions
start Start the rclone mount service start Start rclone mount in background (uses nohup)
stop Stop the rclone mount service start-background Start rclone mount in background (for crontab)
status Show service status stop Stop rclone mount
status Check mount status
mount Manual foreground mount (testing) mount Manual foreground mount (testing)
unmount Unmount manually unmount Unmount manually
@@ -96,55 +97,72 @@ EOF
} }
# ------------------------------------------------------------ # ------------------------------------------------------------
# Hub actions (rclone user service) # Hub actions (simplified - no systemd templates)
# ------------------------------------------------------------ # ------------------------------------------------------------
hub_install() { hub_install() {
local SERVICE_DIR="$HOME/.config/systemd/user" echo "Simplified hub setup:"
local SERVICE_FILE="$SERVICE_DIR/rclone-mount@.service"
local TEMPLATE_FILE="$(dirname "$0")/hub/rclone-mount@.service"
echo "Installing rclone mount systemd user service..."
# Create service directory if it doesn't exist
mkdir -p "$SERVICE_DIR"
# Check if template exists
if [ ! -f "$TEMPLATE_FILE" ]; then
die "Service template not found at $TEMPLATE_FILE"
fi
# Copy service template
cp "$TEMPLATE_FILE" "$SERVICE_FILE"
echo "Copied service template to $SERVICE_FILE"
# Check if user linger is enabled
if ! systemctl --user is-enabled --quiet user@$(id -u).service 2>/dev/null; then
echo "WARNING: User linger may not be enabled. Run: sudo loginctl enable-linger $USER"
echo "You may need to reboot for user services to start automatically."
fi
# Reload systemd
systemctl --user daemon-reload
echo "Systemd user daemon reloaded."
echo "" echo ""
echo "Next steps:" echo "1. Ensure /etc/fuse.conf has 'user_allow_other' uncommented:"
echo "1. Ensure /etc/fuse.conf has 'user_allow_other' uncommented" echo " sudo sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf"
echo "2. Ensure you're in the 'fuse' group: sudo usermod -aG fuse $USER" echo ""
echo "3. Start the service: $0 hub start" echo "2. Ensure you're in the 'fuse' group:"
echo "4. Enable auto-start: systemctl --user enable rclone-mount@${RCLONE_REMOTE}.service" echo " sudo usermod -aG fuse $USER"
echo " (You may need to log out and back in for this to take effect)"
echo ""
echo "3. Create mount point directory:"
echo " mkdir -p \"$MOUNT_POINT\""
echo ""
echo "4. Test manual mount:"
echo " $0 hub mount"
echo ""
echo "5. For auto-start, consider adding to crontab with @reboot:"
echo " crontab -e"
echo " Add: @reboot $0 hub start-background"
echo ""
echo "Note: This simplified version doesn't use systemd services."
} }
hub_start() { hub_start() {
systemctl --user start "rclone-mount@${RCLONE_REMOTE}.service" echo "Starting rclone mount in background..."
mkdir -p "$MOUNT_POINT"
nohup rclone mount "${RCLONE_REMOTE}:" "$MOUNT_POINT" \
--config "${HOME}/.config/rclone/rclone.conf" \
--vfs-cache-mode writes \
--allow-other \
--daemon >/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() { hub_stop() {
systemctl --user stop "rclone-mount@${RCLONE_REMOTE}.service" 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() { hub_status() {
systemctl --user status "rclone-mount@${RCLONE_REMOTE}.service" --no-pager 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() { hub_mount() {
@@ -188,6 +206,7 @@ hub)
case "$ACTION" in case "$ACTION" in
install) hub_install ;; install) hub_install ;;
start) hub_start ;; start) hub_start ;;
start-background) hub_start_background ;;
stop) hub_stop ;; stop) hub_stop ;;
status) hub_status ;; status) hub_status ;;
mount) hub_mount ;; mount) hub_mount ;;

View File

@@ -1,8 +1,13 @@
FROM debian:bookworm-slim FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y autossh openssh-client && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y autossh openssh-client && rm -rf /var/lib/apt/lists/*
RUN echo "PermitRootLogin no" >> /etc/ssh/sshd_config
RUN echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
RUN echo "Subsystem sftp internal-sftp" >> /etc/ssh/sshd_config
ARG UID=1000 ARG UID=1000
ARG GID=1000 ARG GID=1000
RUN groupadd -g ${GID} armbian && useradd -m -u ${UID} -g armbian armbian RUN groupadd -g ${GID} armbian && useradd -m -u ${UID} -g armbian armbian
USER armbian USER armbian
WORKDIR /home/armbian WORKDIR /home/armbian
CMD ["autossh", "-M", "0", "-N"] CMD ["autossh", "-M", "0", "-N"]

View File

@@ -1,15 +0,0 @@
# For now, deprecated in favor of docker tunnel
[Unit]
Description=AutoSSH tunnel from spoke to hub
After=network.target
[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -NT -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -R 11111:localhost:22 -i /home/armbian/.ssh/armbian-brie-202604 armbian@oily.dad
Restart=always
RestartSec=10
User=armbian
[Install]
WantedBy=multi-user.target

View File

@@ -7,6 +7,7 @@ services:
network_mode: host network_mode: host
environment: environment:
- AUTOSSH_GATETIME=0 - AUTOSSH_GATETIME=0
# @@@@@@@@@ BEWARE THE REVERSE TUNNEL PORT AND KEYS WHEN RUNNING THIS ON A NEW SPOKE @@@@@@@@@@
command: > command: >
autossh -M 0 -NT autossh -M 0 -NT
-o "ServerAliveInterval=60" -o "ServerAliveInterval=60"
@@ -17,4 +18,15 @@ services:
volumes: volumes:
- /home/armbian/.ssh/oilykey2026:/home/armbian/.ssh/oilykey2026:ro - /home/armbian/.ssh/oilykey2026:/home/armbian/.ssh/oilykey2026:ro
- /home/armbian/.ssh/known_hosts:/home/armbian/.ssh/known_hosts:ro - /home/armbian/.ssh/known_hosts:/home/armbian/.ssh/known_hosts:ro
- /home/armbian/share:/home/armbian/share # - /home/armbian/share:/home/armbian/
syncthing:
image: syncthing/syncthing
container_name: spoke-syncthing
hostname: spoke-syncthing
restart: unless-stopped
network_mode: host
environment:
- PUID=1000
- PGID=1000
volumes:
- /home/armbian/st:/var/syncthing