Syncthing: Sync Files Between Devices – Without the Cloud
Sync folders directly between your devices, encrypted and without a third-party cloud: Syncthing as peer-to-peer sync behind Traefik, with backup tips.
Table of contents
Dropbox without Dropbox: Syncthing syncs folders directly between your devices – encrypted, without the files ever sitting on someone else’s server. On an always-reachable VPS your server becomes a reliable sync node that mediates even when your laptop and phone are never online at the same time.
What are we building?
An always-on Syncthing node with Syncthing v2.1.2 behind Traefik. By the end you reach the web interface encrypted under your domain, have secured it with a password and can pair your devices via their device IDs so that selected folders sync automatically. Unlike Nextcloud, Syncthing isn’t central storage but a peer-to-peer sync: every device holds a full copy, and the server is just a particularly reliable participant.
Prerequisites
- A server with Traefik running and Docker Compose
- A subdomain pointing at the server –
YOUR_DOMAINbelow - The ability to open port 22000 (TCP+UDP) in the firewall – that’s where the actual sync runs
- Syncthing on at least one other device (desktop, or the Android app)
VPS 1000 G12
4 vCores · 8 GB RAM · 256 GB NVMe
from €10.36/month
A small VPS as an always-on sync node is plenty – Syncthing is frugal.
💶 5 € voucher for new netcup customers:36nc17844976032
(new customers only, no domains)
Step by step
Step 1: Create the directories – and set the permissions right away
Syncthing stores its configuration and the synced data in two folders. The container runs as a normal user (UID 1000), so the folders must belong to that user – this is the most common startup trap:
mkdir -p /opt/syncthing/config /opt/syncthing/data
chown -R 1000:1000 /opt/syncthing/config /opt/syncthing/data
cd /opt/syncthingWithout chown, Syncthing won't start
permission denied" in the log). The chown to UID/GID 1000 before the first start prevents this – more on permissions in Users & permissions.Step 2: The Compose file
Replace YOUR_DOMAIN. The important thing is the difference between the web interface and the sync traffic:
services:
syncthing:
image: syncthing/syncthing:2.1.5
restart: unless-stopped
hostname: koch-server
environment:
PUID: '1000'
PGID: '1000'
volumes:
- ./config:/var/syncthing/config
- ./data:/var/syncthing/Sync
ports:
- "22000:22000/tcp" # sync protocol (direct, not via Traefik)
- "22000:22000/udp" # sync over QUIC
- "21027:21027/udp" # local device discovery
networks: [proxy]
labels:
- "traefik.enable=true"
- "traefik.http.routers.syncthing.rule=Host(`YOUR_DOMAIN`)"
- "traefik.http.routers.syncthing.entrypoints=websecure"
- "traefik.http.routers.syncthing.tls.certresolver=le"
- "traefik.http.services.syncthing.loadbalancer.server.port=8384"
networks:
proxy:
external: trueOnly the web interface (port 8384) runs through Traefik – that’s what the labels handle. The actual sync traffic (port 22000) is its own protocol, not HTTP, so it’s published directly via ports:, not routed through Traefik. This separation is exactly what Understanding Docker networks explains.
Step 3: Open the firewall and start
Open the sync port in the firewall (otherwise the devices won’t find each other):
ufw allow 22000/tcp
ufw allow 22000/udpThen start:
docker compose up -dPatience: Traefik waits for the health check
healthy. But the first check only runs after the default interval of 60 seconds – until then you get a Traefik 404 via the domain. That’s normal; just wait. Check with: docker inspect -f '{{.State.Health.Status}}' syncthing-syncthing-1.Once the status is healthy, the interface responds with valid HTTPS:
curl -sI https://YOUR_DOMAIN/ | head -1HTTP/2 200Step 4: The web interface and the crucial security step
Open https://YOUR_DOMAIN/. The interface is in English by default; you see your device (“This Device”) with its device ID, version and status:

On a fresh install Syncthing warns at the top with a red banner that no GUI password is set yet – and that’s serious: without a password, anyone who reaches the interface can access your files. So under Actions → Settings → GUI immediately set a username and a strong password. After that Syncthing asks for a login on every access – on top of Traefik’s HTTPS.
Set the GUI password in the interface, not via generate as root
syncthing generate as root inside the container instead writes config.xml with the wrong owner – after that Syncthing won’t start (permission denied). If it happens: chown -R 1000:1000 /opt/syncthing/config and restart.Step 5: Pair a second device
Syncthing connects devices via their device ID – a long, unique key. Pairing is mutual: each device has to know the other. Click Add Remote Device:

You find the other device’s ID there under Actions → Show ID (as text and QR code). Enter it here, give it a name and save. On the other device you repeat this with your server’s ID. Once both sides know each other, the device shows as “connected”.
Step 6: Share a folder
Now you define what gets synced. Via Add Folder you choose a path (on the server e.g. /var/syncthing/Sync/documents, which corresponds to the mounted ./data folder) and give it a folder ID. Under the Sharing tab you tick the devices to sync the folder with. On the other device you confirm the incoming share – from then on Syncthing keeps both sides identical automatically.
File versioning as protection against mistakes
.stversions folder. Important: this protects against mistakes, it’s not a backup (see below).When things go wrong
The container won’t start / restart loop with permission denied. The permissions on the config or data folder are wrong. chown -R 1000:1000 /opt/syncthing/config /opt/syncthing/data and restart (see the warning in step 1).
The interface gives a Traefik 404 even though the container is running. The health check isn’t healthy yet – Traefik deliberately doesn’t route then. Wait up to 60 seconds after start and check the status (see the warning in step 3).
Two devices won’t connect. Check three things: is port 22000 (TCP+UDP) open in the firewall? Did you enter the ID on both devices (pairing is mutual)? And is the ID exact (typos are caught easily thanks to a built-in checksum)? A “Disconnected” state with correctly entered IDs almost always points to the firewall port.
A folder is stuck at “Syncing 0%”. Usually the share confirmation is missing on the other side, or the folder ID doesn’t match – it must be identical on both devices. Also check the write permissions in the target folder.
No access after setting the GUI password. Forgot the password? You can reset it in config.xml (<gui> block) by removing the <user> and <password> lines and restarting Syncthing – then the interface is reachable without a login again (and you set it anew immediately).
Maintenance & backups
- Updates. Occasionally bump the image tag (
syncthing/syncthing:2.1.5) to the current version anddocker compose up -d. Syncthing stays compatible within a major version; when jumping to a new major (like v2 here) read the release notes first. Your normal update process handles the rest. - Backup is mandatory – sync is not a backup. This is the most important point: Syncthing mirrors changes, including accidental deletion and ransomware encryption. So back up the sync folder additionally with a real, versioned backup that the sync can’t reach – e.g. Restic on the server. The
configfolder (device IDs, folder shares) belongs in the backup too. - Honest effort. Once set up, Syncthing runs with very little maintenance. Keep an eye on disk space (
df -h) when syncing large folders with versioning, and prune old.stversionsfolders occasionally.
Last updated: Sep 9, 2026
Send feedback: feedback@serverkueche.de
You might also like

Stirling-PDF: The PDF Toolbox on Your Own Server
Merge, compress, convert PDFs and make them searchable with OCR – locally instead of on online services: Stirling-PDF …

HitKeep: self-host privacy-friendly web analytics
Set up HitKeep with Docker and Traefik: cookieless, GDPR-friendly website statistics on your own server – with tracking …

FreshRSS: Your Own RSS Reader
All your news sources in one place, no algorithm and no tracking: FreshRSS as a self-hosted RSS reader behind Traefik – …