1
0
forked from finn/tinyboard

README.md: document syncthing.sh, update architecture, directory structure, script docs, backups, security, and troubleshooting sections

This commit is contained in:
Justin Oros
2026-04-18 18:50:43 -07:00
parent e4db257f53
commit c2aec56490

View File

@@ -1,8 +1,8 @@
# TinyBoard # TinyBoard
A hub-spoke architecture for secure file sharing over SSH tunnels using autossh and rclone. A hub-spoke architecture for secure file sharing and sync over SSH tunnels using autossh, rclone, and Syncthing.
Spokes are ARM devices (e.g. OrangePi, Raspberry Pi) running Armbian that establish reverse SSH tunnels to a central hub server. The hub mounts spoke filesystems via SFTP using rclone, making files accessible across all devices without exposing them to the internet. Spokes are ARM devices (e.g. OrangePi, Raspberry Pi) running Armbian that establish reverse SSH tunnels to a central hub server. The hub mounts spoke filesystems via SFTP using rclone, making files accessible across all devices without exposing them to the internet. Syncthing runs on each spoke for bidirectional file sync.
--- ---
@@ -51,6 +51,21 @@ cd tinyboard
./setup.sh # option 3 (offboard spoke) ./setup.sh # option 3 (offboard spoke)
``` ```
### Configuring Syncthing
After the hub and at least one spoke are set up, run `syncthing.sh` on either device to manage Syncthing devices and folders interactively:
```bash
./syncthing.sh
```
The typical pairing flow:
1. Run option 1 (Show This Device's ID) on the spoke — copy the ID
2. Run option 4 (Add Device) on the hub — paste the spoke's ID
3. Run option 1 (Show This Device's ID) on the hub — copy the ID
4. Run option 4 (Add Device) on the spoke — paste the hub's ID
5. On both devices, run option 7 (Add Folder) or option 9 (Share Folder with Device) to share folders between them
--- ---
## Architecture ## Architecture
@@ -63,6 +78,9 @@ cd tinyboard
autossh container ──────────► sshd (GatewayPorts) autossh container ──────────► sshd (GatewayPorts)
reverse tunnel port 111xx reverse tunnel port 111xx
syncthing container ◄──────────► syncthing (hub or other spokes)
file sync
rclone SFTP mount rclone SFTP mount
~/mnt/<spoke-name>/ ~/mnt/<spoke-name>/
``` ```
@@ -75,11 +93,12 @@ Spokes initiate outbound SSH connections to the hub, creating reverse tunnels. T
``` ```
tinyboard/ tinyboard/
├── setup.sh ← entry point ├── setup.sh ← entry point for hub/spoke setup
├── syncthing.sh ← manage Syncthing devices and folders
├── spoke/ ├── spoke/
│ ├── setup-network.sh ← configure static IP before setup │ ├── setup-network.sh ← configure static IP before setup
│ ├── setup-spoke.sh ← automated spoke setup │ ├── setup-spoke.sh ← automated spoke setup
│ ├── compose.yaml ← Docker Compose for autossh + syncthing │ ├── compose.yaml ← Docker Compose for autossh + Syncthing
│ ├── Dockerfile ← autossh container │ ├── Dockerfile ← autossh container
│ └── armbian.not_logged_in_yet ← Armbian first-boot WiFi config template │ └── armbian.not_logged_in_yet ← Armbian first-boot WiFi config template
└── hub/ └── hub/
@@ -94,23 +113,38 @@ tinyboard/
### `setup.sh` ### `setup.sh`
Entry point. Presents a menu: Entry point. Presents a menu:
0. Reconfigure network (static IP via netplan — SSH session will drop, reconnect) - 0) Reconfigure network (static IP via netplan — SSH session will drop, reconnect)
1. Set up this device as a new spoke - 1) Set up this device as a new spoke
2. Onboard a new spoke from the hub - 2) Onboard a new spoke from the hub
3. Offboard a spoke from the hub - 3) Offboard a spoke from the hub
4. Set up this device as a new hub - 4) Set up this device as a new hub
### `syncthing.sh`
Interactive Syncthing management. Can be run on the hub or any spoke. Presents a menu:
- 1) Show This Device's ID
- 2) Pending Devices
- 3) List Devices
- 4) Add Device
- 5) Remove Device
- 6) List Folders
- 7) Add Folder
- 8) Remove Folder
- 9) Share Folder with Device
- 10) Unshare Folder from Device
Requires Docker and a running Syncthing container. Auto-discovers the container and API key.
### `spoke/setup-network.sh` ### `spoke/setup-network.sh`
Run as root on a new spoke before `setup.sh`. Configures a static IP via netplan. Supports both WiFi and wired interfaces. Automatically reverts if network connectivity is lost after applying the new config. Run as root on a new spoke before `setup.sh`. Configures a static IP via netplan. Supports both WiFi and wired interfaces. Backs up the existing netplan config with a timestamp before writing. Automatically reverts if network connectivity is lost after applying.
### `spoke/setup-spoke.sh` ### `spoke/setup-spoke.sh`
Run as root on a new spoke. Handles: Run as root on a new spoke. Handles:
- Package installation (apt/dnf/yum/pacman) - Package installation (apt/dnf/yum/pacman)
- Docker installation - Docker installation
- SSH server setup - SSH server setup
- Hostname configuration - Hostname configuration (validated for safe characters)
- SSH key generation and hub authorization - SSH key generation and hub authorization
- Tunnel port auto-detection on the hub - Tunnel port auto-detection on the hub (scans up to 100 ports)
- Docker image build and container start - Docker image build and container start
- Optional password auth disable - Optional password auth disable
@@ -119,7 +153,7 @@ Run as root on a new hub server. Handles:
- Package installation (apt/dnf/yum/pacman) - Package installation (apt/dnf/yum/pacman)
- rclone installation - rclone installation
- Hub user creation - Hub user creation
- SSH server configuration (GatewayPorts, AllowTcpForwarding) - SSH server configuration (GatewayPorts, AllowTcpForwarding, ClientAliveInterval)
- FUSE configuration - FUSE configuration
- rclone config directory setup - rclone config directory setup
- Optional password auth disable - Optional password auth disable
@@ -127,14 +161,13 @@ Run as root on a new hub server. Handles:
### `hub/onboard-spoke.sh` ### `hub/onboard-spoke.sh`
Run as the hub user after a spoke connects. Handles: Run as the hub user after a spoke connects. Handles:
- SSH key generation and deployment to spoke - SSH key generation and deployment to spoke
- rclone remote configuration - rclone remote configuration (with trailing newline guard)
- Spoke registration in `~/.config/tinyboard/spokes` - Spoke registration in `~/.config/tinyboard/spokes`
- Per-spoke crontab entry for auto-mount on reboot
### `hub/offboard-spoke.sh` ### `hub/offboard-spoke.sh`
Run as the hub user to remove a spoke. Handles: Run as the hub user to remove a spoke. Handles:
- Unmounting the spoke filesystem - Unmounting the spoke filesystem
- Removing the crontab entry - Crontab backup (timestamped to `~/.config/tinyboard/`) then entry removal
- Removing the rclone remote - Removing the rclone remote
- Optionally removing the hub SSH key - Optionally removing the hub SSH key
- Removing from the spoke registry - Removing from the spoke registry
@@ -150,18 +183,31 @@ rocky 11113 /home/armbian/.ssh/armbian-rocky-202504 /home/armbian/mnt/rocky
gouda 11114 /home/armbian/.ssh/armbian-gouda-202504 /home/armbian/mnt/gouda gouda 11114 /home/armbian/.ssh/armbian-gouda-202504 /home/armbian/mnt/gouda
``` ```
Each spoke gets its own mount point at `~/mnt/<spoke-name>/` and a dedicated rclone crontab entry. Each spoke gets its own mount point at `~/mnt/<spoke-name>/` and a dedicated rclone remote.
---
## Backups
Scripts that modify critical configs create timestamped backups before writing:
- **Netplan:** `/root/.config/tinyboard/netplan-backups/<filename>.<datetime>`
- **Crontab:** `~/.config/tinyboard/crontab.<datetime>`
Restore hints are printed to the terminal after each backup.
--- ---
## Security ## Security
- All communication is over SSH tunnels — no spoke ports exposed to the internet - All communication is over SSH tunnels — no spoke ports exposed to the internet
- SSH keys are used for all authentication - SSH keys used for all authentication
- Scripts check and auto-fix unsafe file permissions (600/400) - Scripts check and auto-fix unsafe file permissions (600/400)
- Password authentication can be disabled during setup - Password authentication can be disabled during setup
- Scripts refuse to disable password auth if no authorized keys are present (lockout prevention) - Scripts refuse to disable password auth if no authorized keys are present (lockout prevention)
- Netplan changes are verified with a 30-second connectivity check before being made permanent - Netplan changes verified with a 30-second connectivity check before being made permanent
- Spoke names validated against `^[a-zA-Z0-9._-]+$` to prevent injection into hostnames and container names
- Syncthing admin UI bound to `127.0.0.1:8384` only (not exposed on the network)
--- ---
@@ -170,6 +216,7 @@ Each spoke gets its own mount point at `~/mnt/<spoke-name>/` and a dedicated rcl
Before committing, ensure the following do not contain real credentials: Before committing, ensure the following do not contain real credentials:
- `spoke/armbian.not_logged_in_yet` — contains WiFi SSID, password, and user passwords - `spoke/armbian.not_logged_in_yet` — contains WiFi SSID, password, and user passwords
- `spoke/compose.yaml` — may contain hub hostname after spoke setup runs
--- ---
@@ -185,10 +232,18 @@ grep -r "beta.armbian" /etc/apt/sources.list /etc/apt/sources.list.d/
Open the file that contains it (usually `/etc/apt/sources.list.d/armbian.sources`) and comment out or remove the line referencing `beta.armbian.com`, then run `apt update` again. Open the file that contains it (usually `/etc/apt/sources.list.d/armbian.sources`) and comment out or remove the line referencing `beta.armbian.com`, then run `apt update` again.
### Tunnel is up but rclone mount fails
Check that FUSE is configured on the hub (`user_allow_other` in `/etc/fuse.conf`) and that the hub user is in the `fuse` group. You may need to log out and back in for group membership to take effect.
### Syncthing container not found by syncthing.sh
The script looks for a running container with "syncthing" in its name. Run `docker ps` to confirm the container is running. If it stopped, run `docker compose up -d` from the `spoke/` directory.
--- ---
## Requirements ## Requirements
**Spoke:** Armbian (Debian-based), ARM device, Docker, autossh, git **Spoke:** Armbian (or any Debian/Ubuntu/RHEL/Arch Linux), ARM device, Docker, autossh, git
**Hub:** Any Linux server (Debian/Ubuntu/RHEL/Arch), rclone, fuse, openssh-server **Hub:** Any Linux server (Debian/Ubuntu/RHEL/Arch), rclone, fuse, openssh-server, python3