forked from finn/tinyboard
rewrite README with quickstart and updated architecture docs
This commit is contained in:
307
README.md
307
README.md
@@ -1,208 +1,179 @@
|
|||||||
# TinyBoard Hub-Spoke File Sharing System
|
# TinyBoard
|
||||||
|
|
||||||
A hub-spoke architecture for secure file sharing over SSH tunnels using autossh and rclone.
|
A hub-spoke architecture for secure file sharing over SSH tunnels using autossh and rclone.
|
||||||
|
|
||||||
## Architecture Overview
|
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.
|
||||||
|
|
||||||
This system implements a hub-and-spoke model where:
|
---
|
||||||
- **Spokes**: Raspberry Pi devices running Armbian that establish reverse SSH tunnels to the hub
|
|
||||||
- **Hub**: Central server that mounts spoke filesystems via SFTP using rclone
|
|
||||||
|
|
||||||
### Key Components
|
## Quickstart
|
||||||
|
|
||||||
1. **Spoke Side** (`spoke/` directory):
|
### Setting up a new Hub
|
||||||
- Docker-based autossh tunnel container
|
|
||||||
- Configuration files for spoke setup
|
|
||||||
- Hostname assignment based on MAC address
|
|
||||||
|
|
||||||
2. **Hub Side** (`hub/` directory):
|
On a fresh Debian/Ubuntu VPS or server:
|
||||||
- Rclone SFTP mount configuration
|
|
||||||
- Systemd user service for automatic mounting
|
|
||||||
|
|
||||||
3. **Management Script** (`hubspoke-helper.sh`):
|
```bash
|
||||||
- Unified interface for managing both hub and spoke components
|
apt install git
|
||||||
|
git clone https://gut.oily.dad/oily.mom/tinyboard
|
||||||
|
cd tinyboard
|
||||||
|
./setup.sh # choose option 4
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setting up a new Spoke
|
||||||
|
|
||||||
|
On a fresh Armbian device:
|
||||||
|
|
||||||
|
1. Modify `spoke/armb-not_logged_in_yet` accordingly, then drop it onto the SD card as `/root/.not_logged_in_yet` before first boot (WiFi credentials)
|
||||||
|
2. Boot, SSH in as root
|
||||||
|
3. Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install git
|
||||||
|
git clone https://gut.oily.dad/oily.mom/tinyboard
|
||||||
|
cd tinyboard
|
||||||
|
./setup-network.sh # configure static IP — SSH session will drop, reconnect
|
||||||
|
./setup.sh # choose option 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Onboarding a Spoke from the Hub
|
||||||
|
|
||||||
|
Once the spoke tunnel is up, run on the hub:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tinyboard
|
||||||
|
./setup.sh # choose option 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Offboarding a Spoke from the Hub
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tinyboard
|
||||||
|
./setup.sh # choose option 3
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
[ Spoke ] [ Hub ]
|
||||||
|
OrangePi / RPi VPS / Server
|
||||||
|
Armbian Any Linux
|
||||||
|
|
||||||
|
autossh container ──────────► sshd (GatewayPorts)
|
||||||
|
reverse tunnel port 111xx
|
||||||
|
|
||||||
|
rclone SFTP mount
|
||||||
|
~/mnt/<spoke-name>/
|
||||||
|
```
|
||||||
|
|
||||||
|
Spokes initiate outbound SSH connections to the hub, creating reverse tunnels. The hub then uses rclone to mount each spoke's filesystem over SFTP through the tunnel. No inbound ports need to be open on the spoke.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
tinyboard/
|
tinyboard/
|
||||||
├── hubspoke-helper.sh # Main management script
|
├── setup.sh ← entry point
|
||||||
├── hub/
|
├── setup-network.sh ← configure static IP on spoke before setup
|
||||||
│ └── rclone.conf # Rclone SFTP configuration
|
|
||||||
├── spoke/
|
├── spoke/
|
||||||
│ ├── compose.yaml # Docker Compose for autossh tunnel
|
│ ├── setup-spoke.sh ← automated spoke setup
|
||||||
│ ├── Dockerfile # autossh container image
|
│ ├── compose.yaml ← Docker Compose for autossh + syncthing
|
||||||
│ ├── autohostname.sh # Hostname assignment by MAC address
|
│ ├── Dockerfile ← autossh container
|
||||||
│ ├── aptprimary.sh # Initial package installation
|
│ └── armb-not_logged_in_yet ← Armbian first-boot WiFi config template
|
||||||
│ ├── clean_sensitive.sh # Clean WiFi/password from configs
|
└── hub/
|
||||||
│ └── armb-not_logged_in_yet # Armbian first-boot configuration
|
├── setup-hub.sh ← automated hub setup
|
||||||
└── README.md # This file
|
├── onboard-spoke.sh ← add a new spoke to the hub
|
||||||
|
└── offboard-spoke.sh ← remove a spoke from the hub
|
||||||
```
|
```
|
||||||
|
|
||||||
## Key File Handling (Manual Setup)
|
---
|
||||||
|
|
||||||
**IMPORTANT**: The following files must be manually created/configured as they contain sensitive information:
|
## Setup Scripts
|
||||||
|
|
||||||
### SSH Keys
|
### `setup.sh`
|
||||||
- `~/.ssh/oilykey2026` on spokes (referenced in `spoke/compose.yaml`)
|
Entry point. Presents a menu:
|
||||||
- `~/.ssh/armbian-brie-202604` on hub (referenced in `hub/rclone.conf`)
|
1. Set up this device as a new spoke
|
||||||
- These keys must be manually generated and distributed
|
2. Onboard a new spoke from the hub
|
||||||
|
3. Offboard a spoke from the hub
|
||||||
|
4. Set up this device as a new hub
|
||||||
|
|
||||||
### Rclone Configuration
|
### `setup-network.sh`
|
||||||
- `~/.config/rclone/rclone.conf` on hub must be manually created
|
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.
|
||||||
- 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
|
### `spoke/setup-spoke.sh`
|
||||||
- `~/.config/systemd/user/rclone-mount@.service` must be manually copied from `hub/rclone-mount@.service`
|
Run as root on a new spoke. Handles:
|
||||||
|
- Package installation (apt/dnf/yum/pacman)
|
||||||
|
- Docker installation
|
||||||
|
- SSH server setup
|
||||||
|
- Hostname configuration
|
||||||
|
- SSH key generation and hub authorization
|
||||||
|
- Tunnel port auto-detection on the hub
|
||||||
|
- Docker image build and container start
|
||||||
|
- Optional password auth disable
|
||||||
|
|
||||||
## Spoke Setup (Raspberry Pi / Armbian)
|
### `hub/setup-hub.sh`
|
||||||
|
Run as root on a new hub server. Handles:
|
||||||
|
- Package installation (apt/dnf/yum/pacman)
|
||||||
|
- rclone installation
|
||||||
|
- Hub user creation
|
||||||
|
- SSH server configuration (GatewayPorts, AllowTcpForwarding)
|
||||||
|
- FUSE configuration
|
||||||
|
- rclone config directory setup
|
||||||
|
- Optional password auth disable
|
||||||
|
|
||||||
### Initial Setup
|
### `hub/onboard-spoke.sh`
|
||||||
1. Write Armbian minimal image to SD card
|
Run as the hub user after a spoke connects. Handles:
|
||||||
2. Copy `spoke/armb-not_logged_in_yet` to SD card root `/root/.not_logged_in_yet` (contains WiFi credentials)
|
- SSH key generation and deployment to spoke
|
||||||
3. Boot device, SSH in as root with password "1234"
|
- rclone remote configuration
|
||||||
4. After first login and setup tasks, `.not_logged_in_yet` will be processed for root and armbian user credentials
|
- Spoke registration in `~/.config/tinyboard/spokes`
|
||||||
5. Clone this repository: `git clone <repo-url>`
|
- Per-spoke crontab entry for auto-mount on reboot
|
||||||
6. Run `spoke/aptprimary.sh` to install required packages
|
|
||||||
7. Run `spoke/autohostname.sh` to assign hostname based on MAC address
|
|
||||||
8. Reboot and test as armbian user
|
|
||||||
|
|
||||||
### SSH Key Setup
|
### `hub/offboard-spoke.sh`
|
||||||
1. Generate SSH key pair on hub: `ssh-keygen -t ed25519 -f ~/.ssh/armbian-brie-202604`
|
Run as the hub user to remove a spoke. Handles:
|
||||||
2. Copy public key to spoke: `ssh-copy-id -i ~/.ssh/armbian-brie-202604.pub armbian@<spoke-ip>`
|
- Unmounting the spoke filesystem
|
||||||
3. Generate spoke key: `ssh-keygen -t ed25519 -f ~/.ssh/oilykey2026`
|
- Removing the crontab entry
|
||||||
4. Copy public key to hub for reverse tunnel authentication
|
- Removing the rclone remote
|
||||||
|
- Optionally removing the hub SSH key
|
||||||
|
- Removing from the spoke registry
|
||||||
|
|
||||||
### Docker Tunnel Setup
|
---
|
||||||
```bash
|
|
||||||
# Build the autossh container
|
|
||||||
./hubspoke-helper.sh spoke build
|
|
||||||
|
|
||||||
# Start the tunnel
|
## Spoke Registry
|
||||||
./hubspoke-helper.sh spoke start
|
|
||||||
|
|
||||||
# Check status
|
The hub maintains a registry of connected spokes at `~/.config/tinyboard/spokes`:
|
||||||
./hubspoke-helper.sh spoke status
|
|
||||||
|
|
||||||
# View logs
|
```
|
||||||
./hubspoke-helper.sh spoke logs
|
rocky 11113 /home/armbian/.ssh/armbian-rocky-202504 /home/armbian/mnt/rocky
|
||||||
|
gouda 11114 /home/armbian/.ssh/armbian-gouda-202504 /home/armbian/mnt/gouda
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hub Setup (Central Server)
|
Each spoke gets its own mount point at `~/mnt/<spoke-name>/` and a dedicated rclone crontab entry.
|
||||||
|
|
||||||
### Rclone Configuration
|
---
|
||||||
1. Install rclone: `apt install rclone fuse`
|
|
||||||
2. Create config directory: `mkdir -p ~/.config/rclone`
|
|
||||||
3. Copy and customize `hub/rclone.conf` to `~/.config/rclone/rclone.conf`
|
|
||||||
4. Update key_file path to point to your SSH private key
|
|
||||||
|
|
||||||
### FUSE Configuration
|
## Security
|
||||||
```bash
|
|
||||||
# Allow other users to access mounts (if needed)
|
|
||||||
sudo sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf
|
|
||||||
|
|
||||||
# Add user to fuse group
|
- All communication is over SSH tunnels — no spoke ports exposed to the internet
|
||||||
sudo groupadd fuse
|
- SSH keys are used for all authentication
|
||||||
sudo usermod -aG fuse $USER
|
- Scripts check and auto-fix unsafe file permissions (600/400)
|
||||||
```
|
- Password authentication can be disabled during setup
|
||||||
|
- 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
|
||||||
|
|
||||||
## Usage
|
---
|
||||||
|
|
||||||
### Managing Spoke Tunnels
|
## Sensitive Files
|
||||||
- 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
|
Before committing, ensure the following do not contain real credentials:
|
||||||
# Build autossh container
|
|
||||||
./hubspoke-helper.sh spoke build
|
|
||||||
|
|
||||||
# Start/stop/restart tunnel
|
- `spoke/armb-not_logged_in_yet` — contains WiFi SSID, password, and user passwords
|
||||||
./hubspoke-helper.sh spoke start
|
|
||||||
./hubspoke-helper.sh spoke stop
|
|
||||||
./hubspoke-helper.sh spoke restart
|
|
||||||
|
|
||||||
# Check status and logs
|
---
|
||||||
./hubspoke-helper.sh spoke status
|
|
||||||
./hubspoke-helper.sh spoke logs
|
|
||||||
|
|
||||||
# Show manual autossh command
|
## Requirements
|
||||||
./hubspoke-helper.sh spoke show-cmd
|
|
||||||
```
|
|
||||||
|
|
||||||
### Managing Hub Mounts
|
**Spoke:** Armbian (Debian-based), ARM device, Docker, autossh, git
|
||||||
|
|
||||||
#### 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
|
|
||||||
|
|
||||||
# Start/stop rclone mount
|
|
||||||
./hubspoke-helper.sh hub start
|
|
||||||
./hubspoke-helper.sh hub stop
|
|
||||||
|
|
||||||
# Check service status
|
|
||||||
./hubspoke-helper.sh hub status
|
|
||||||
|
|
||||||
# Manual mount/unmount for testing
|
|
||||||
./hubspoke-helper.sh hub mount
|
|
||||||
./hubspoke-helper.sh hub unmount
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration Variables
|
|
||||||
|
|
||||||
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/hub`)
|
|
||||||
|
|
||||||
## Security Notes
|
|
||||||
|
|
||||||
1. **SSH Keys**: Always use strong key pairs and protect private keys
|
|
||||||
2. **Configuration Files**: Use `spoke/clean_sensitive.sh` to remove WiFi credentials before committing
|
|
||||||
3. **Firewall**: Ensure proper firewall rules on hub (port 11111 for reverse tunnels)
|
|
||||||
4. **User Permissions**: Run services with minimal required privileges
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Spoke Tunnel Issues
|
|
||||||
- Check Docker container logs: `./hubspoke-helper.sh spoke logs`
|
|
||||||
- Verify SSH key permissions: `chmod 600 ~/.ssh/oilykey2026`
|
|
||||||
- Test SSH connection manually: `ssh -p 11111 armbian@localhost`
|
|
||||||
|
|
||||||
### Hub Mount Issues
|
|
||||||
- Check service status: `./hubspoke-helper.sh hub status`
|
|
||||||
- Test rclone manually: `rclone lsd brie-sftp:`
|
|
||||||
- Verify fuse configuration: `ls -la /etc/fuse.conf`
|
|
||||||
- Check user groups: `groups $USER`
|
|
||||||
|
|
||||||
### Network Issues
|
|
||||||
- Ensure spokes can reach hub on SSH port (22)
|
|
||||||
- Verify reverse tunnel port (11111) is not blocked by firewall
|
|
||||||
- Check DNS resolution on spokes for hub hostname
|
|
||||||
|
|
||||||
## Maintenance
|
|
||||||
|
|
||||||
### Updating Configuration
|
|
||||||
1. Update `spoke/compose.yaml` for new spoke hostnames
|
|
||||||
2. Update `hub/rclone.conf` for new spoke connections
|
|
||||||
3. Update `spoke/autohostname.sh` for new MAC addresses
|
|
||||||
|
|
||||||
### Adding New Spokes
|
|
||||||
1. Follow Spoke Setup steps for new device
|
|
||||||
2. Add MAC address to `spoke/autohostname.sh`
|
|
||||||
3. Update hub's SSH authorized_keys with new spoke public key
|
|
||||||
4. Add new rclone remote configuration if needed
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is for personal use. Adapt as needed for your environment.
|
|
||||||
|
|
||||||
|
**Hub:** Any Linux server (Debian/Ubuntu/RHEL/Arch), rclone, fuse, openssh-server
|
||||||
|
|||||||
Reference in New Issue
Block a user