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/
├── hubspoke-helper.sh # Main management script
├── hub/
│ ├── rclone-mount@.service # Systemd user service template
│ └── rclone.conf # Rclone SFTP configuration
├── spoke/
│ ├── compose.yaml # Docker Compose for autossh tunnel
│ ├── Dockerfile # autossh container image
│ ├── autossh-tunnel.service # Legacy systemd service (deprecated)
│ ├── autohostname.sh # Hostname assignment by MAC address
│ ├── aptprimary.sh # Initial package installation
│ ├── clean_sensitive.sh # Clean WiFi/password from configs
@@ -54,6 +52,7 @@ tinyboard/
- `~/.config/rclone/rclone.conf` on hub must be manually created
- Use `hub/rclone.conf` as a template
- Update host, port, and key_file paths as needed
- Manually create rclone mount and permission it (`/mnt/hub` for example)
### Systemd Service Files
- `~/.config/systemd/user/rclone-mount@.service` must be manually copied from `hub/rclone-mount@.service`
@@ -62,9 +61,9 @@ tinyboard/
### Initial Setup
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"
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>`
6. Run `spoke/aptprimary.sh` to install required packages
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`
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
```bash
# Allow other users to access mounts (if needed)
@@ -118,6 +111,10 @@ sudo usermod -aG fuse $USER
## Usage
### 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
# Build autossh container
./hubspoke-helper.sh spoke build
@@ -136,6 +133,13 @@ sudo usermod -aG fuse $USER
```
### Managing Hub Mounts
#### Crontab entry:
```
@reboot /home/armbian/tinyboard/hubspoke-helper.sh hub start-background
```
#### Deprecated: systemd
```bash
# Install systemd service (after manual file placement)
./hubspoke-helper.sh hub install
@@ -158,7 +162,7 @@ Environment variables can override defaults:
- `TUNNEL_DIR`: Directory containing spoke Docker files (default: `~/tinyboard/spoke`)
- `COMPOSE_FILE`: Docker compose file path (default: `$TUNNEL_DIR/compose.yaml`)
- `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

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
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
# 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
@@ -12,7 +12,7 @@ set -euo pipefail
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:-$HOME/mnt/$RCLONE_REMOTE}"
MOUNT_POINT="${MOUNT_POINT:-/mnt/hub/$RCLONE_REMOTE}"
# ------------------------------------------------------------
# Usage
@@ -30,11 +30,12 @@ SPOKE ACTIONS (docker-based, no systemd):
logs Show container logs
show-cmd Show manual autossh command (non-docker)
HUB ACTIONS (systemd user service for rclone mount):
install Install the rclone user service (needs service file)
start Start the rclone mount service
stop Stop the rclone mount service
status Show service status
HUB ACTIONS (simplified rclone mount - no systemd):
install Show simplified setup instructions
start Start rclone mount in background (uses nohup)
start-background Start rclone mount in background (for crontab)
stop Stop rclone mount
status Check mount status
mount Manual foreground mount (testing)
unmount Unmount manually
@@ -96,55 +97,72 @@ EOF
}
# ------------------------------------------------------------
# Hub actions (rclone user service)
# Hub actions (simplified - no systemd templates)
# ------------------------------------------------------------
hub_install() {
local SERVICE_DIR="$HOME/.config/systemd/user"
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 "Simplified hub setup:"
echo ""
echo "Next steps:"
echo "1. Ensure /etc/fuse.conf has 'user_allow_other' uncommented"
echo "2. Ensure you're in the 'fuse' group: sudo usermod -aG fuse $USER"
echo "3. Start the service: $0 hub start"
echo "4. Enable auto-start: systemctl --user enable rclone-mount@${RCLONE_REMOTE}.service"
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 ""
echo "2. Ensure you're in the 'fuse' group:"
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() {
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() {
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() {
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() {
@@ -188,6 +206,7 @@ hub)
case "$ACTION" in
install) hub_install ;;
start) hub_start ;;
start-background) hub_start_background ;;
stop) hub_stop ;;
status) hub_status ;;
mount) hub_mount ;;

View File

@@ -1,8 +1,13 @@
FROM debian:bookworm-slim
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 GID=1000
RUN groupadd -g ${GID} armbian && useradd -m -u ${UID} -g armbian armbian
USER 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
environment:
- AUTOSSH_GATETIME=0
# @@@@@@@@@ BEWARE THE REVERSE TUNNEL PORT AND KEYS WHEN RUNNING THIS ON A NEW SPOKE @@@@@@@@@@
command: >
autossh -M 0 -NT
-o "ServerAliveInterval=60"
@@ -17,4 +18,15 @@ services:
volumes:
- /home/armbian/.ssh/oilykey2026:/home/armbian/.ssh/oilykey2026: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