Picture this: it’s 2 AM, your central NAS freezes during a heavy storage scrub, and you urgently need an Ansible playbook or SSH key stored on it. When everything depends on a single hub, one hardware glitch halts your entire workflow. Peer-to-peer (P2P) synchronization solves this issue. By keeping local copies on each active endpoint, your files remain accessible even when your primary server goes dark.
Comparing Centralized Storage, Cloud Drives, and P2P Sync
Before writing compose files, look at how these three storage models handle network splits and host crashes.
| Feature | Centralized NAS (NFS / SMB / Nextcloud) | Proprietary Cloud (Google Drive / Dropbox) | Decentralized P2P (Syncthing) |
|---|---|---|---|
| Topology | Client-Server (Single Hub) | Centralized Third-Party Cloud | Decentralized Mesh (Node-to-Node) |
| LAN Throughput | Line-rate (1 Gbps / 10 Gbps) | Capped by ISP uplink (often 20–50 Mbps) | Line-rate (110+ MB/s over 1GbE, TLS encrypted) |
| Offline Resilience | Zero if the main NAS drops offline | Zero without an active internet connection | High: Connected LAN devices continue syncing |
| Data Privacy | Self-hosted and fully private | Stored on remote corporate infrastructure | End-to-end TLS; data stays on your own disks |
| Memory Footprint | Moderate to heavy (500MB–2GB+ for PHP/DB stacks) | Negligible on server (proprietary desktop client) | Very light (typically 50MB–120MB RAM in Go) |
Pros and Cons in a Self-Hosted Environment
Syncthing is a continuous, block-level synchronization engine, not an archival backup utility. Recognizing that distinction helps you place it where it performs best.
Strengths
- No Storage Paywalls: Sync quotas depend solely on the available disk space across your nodes.
- Fast Local Discovery: Nodes on the same subnet use IPv4/IPv6 broadcast packets (port 21027/UDP) to link up within seconds, bypassing WAN relays entirely.
- Block-Level Delta Updates: Changing a few lines inside a 5GB virtual disk image triggers transfers for only the modified 128KB–4MB chunks.
- Built-In Versioning: Staggered, Trash Can, and Simple versioning policies protect your directories against accidental file overwrites and ransomware.
Trade-offs
- No Web-Based File Explorer: Syncthing syncs raw files directly to disk. It does not include built-in document editors or media players.
- Concurrent Node Availability: Data moves directly between peers. At least two devices must be online simultaneously for a transfer to finish, which is why an always-on mini PC or server makes an ideal anchor.
- Kernel Watch Exhaustion: Tracking large folder hierarchies (like a 40,000-file
node_modulesdirectory) can quickly consume default Linux file watcher handles.
Recommended Network and Port Architecture
In a standard homelab setup, run an always-on Syncthing container on a low-power server or NAS. Your laptops, desktops, and mobile devices pair to this node as an always-ready synchronization bridge.
Expose these specific container ports directly to ensure fast LAN discovery and native QUIC protocol performance:
8384/tcp: Web administrative GUI.22000/tcp&22000/udp: Core TLS sync traffic and QUIC data transfers.21027/udp: Local broadcast and multicast discovery.
Step-by-Step Docker Compose Deployment
Step 1: Check Permissions and Create Storage Paths
Identify your user credentials first. Then build dedicated folders for configuration states and synchronized shares:
# Check your active user ID and group ID
id
# Create persistent storage directories
sudo mkdir -p /srv/syncthing/config /srv/syncthing/data
sudo chown -R $USER:$USER /srv/syncthing
chmod -R 755 /srv/syncthing
Step 2: Write the Docker Compose Configuration
Save the following configuration as /srv/syncthing/docker-compose.yml:
services:
syncthing:
image: syncthing/syncthing:latest
container_name: syncthing
hostname: homelab-syncthing-node01
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
volumes:
- /srv/syncthing/config:/var/syncthing/config
- /srv/syncthing/data:/var/syncthing/Sync
ports:
- "8384:8384" # Web GUI
- "22000:22000/tcp" # TCP sync traffic
- "22000:22000/udp" # QUIC sync traffic
- "21027:21027/udp" # Local discovery
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fk", "http://localhost:8384/rest/noauth/health"]
interval: 30s
timeout: 10s
retries: 3
Step 3: Tune Kernel Inotify Limits and Launch
Default Linux inotify caps (often 8,192 watches) cause synchronization lag on large codebases. Raise this limit before spinning up the container:
# Increase inotify user watch allocation to 204,800
echo "fs.inotify.max_user_watches=204800" | sudo tee -a /etc/sysctl.d/90-syncthing.conf
sudo sysctl --system
# Launch Syncthing in detached mode
cd /srv/syncthing
docker compose up -d
# Inspect live startup logs
docker compose logs -f syncthing
Step 4: Initial Hardening and Pairing
- Open your browser and visit
http://<YOUR_SERVER_IP>:8384. - Go to Actions > Settings > GUI. Enter an admin username, set a strong 16+ character password, and check Use HTTPS for GUI.
- Click Actions > Show ID to copy your node’s 56-character cryptographic device fingerprint.
- Open Syncthing on your laptop, click Add Remote Device, paste the server ID, and confirm the handshake prompt on both sides.
- In the shared folder options, enable Staggered Versioning. This automatically preserves hourly versions for the first day, daily copies for a month, and weekly snapshots thereafter.
Step 5: Quick Troubleshooting Commands
# If peers show 'Relayed' instead of direct LAN connections:
# Ensure firewall rules permit discovery and sync ports
sudo ufw allow 22000/tcp
sudo ufw allow 22000/udp
sudo ufw allow 21027/udp
sudo ufw reload
# If you run into folder sync permission errors:
# Verify host directory ownership matches your PUID/PGID (1000:1000)
ls -ld /srv/syncthing/data

