Skip to content
Serverküche
Search

Loading search … (only available on the published site).

Applications Difficulty: Intermediate

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.

· 7 min read ·Duration: approx. 45 minutes
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

🍳 Recommendation Ad

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.

Go to netcup →

💶 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:

Terminal
mkdir -p /opt/syncthing/config /opt/syncthing/data
chown -R 1000:1000 /opt/syncthing/config /opt/syncthing/data
cd /opt/syncthing

Without chown, Syncthing won't start

If the folders belong to root (the default for freshly created directories), Syncthing can’t write its certificate and configuration and enters a restart loop ("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:

YAML
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: true

Only 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):

Terminal
ufw allow 22000/tcp
ufw allow 22000/udp

Then start:

Terminal
docker compose up -d

Patience: Traefik waits for the health check

The Syncthing image ships its own health check, and Traefik only routes to a container once it’s 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:

Terminal
curl -sI https://YOUR_DOMAIN/ | head -1
Ausgabe
HTTP/2 200

Step 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:

The Syncthing web interface with your own device koch-server, version v2.1.5 and the device ID
The web interface: this device with its device ID, and below it sections for folders and remote devices

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

Set the password through the web interface. Running 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:

The “Add Device” dialog with fields for device ID, name and group
A device is added by its device ID – you find the ID on the other device under \"Actions → Show ID\"

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

Enable file versioning per folder in its settings (e.g. “Simple Versioning”, 5 versions). If one device deletes or overwrites a file, the old version is kept on the other devices in a .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 and docker 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 config folder (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 .stversions folders occasionally.

Last updated: Sep 9, 2026

You might also like

FreshRSS: Your Own RSS Reader
Applications Intermediate

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 – …

· 5 min read