Syncthing File Synchronization Installation

Syncthing is an open-source, peer-to-peer file synchronization tool that keeps files in sync across multiple devices without relying on a central cloud service. Data is transferred directly between devices using TLS encryption, making Syncthing suitable for syncing sensitive files, self-hosted backups, and distributed content workflows on Linux.

Prerequisites

  • Ubuntu/Debian or CentOS/Rocky Linux VPS or physical server
  • Ports 22000/TCP, 22000/UDP, and 21027/UDP open between syncing devices
  • Basic familiarity with the Linux terminal

Installing Syncthing

# Ubuntu/Debian - add official APT repository
curl -s https://syncthing.net/release-key.txt | sudo apt-key add -
echo "deb https://apt.syncthing.net/ syncthing stable" | \
  sudo tee /etc/apt/sources.list.d/syncthing.list
sudo apt-get update
sudo apt-get install -y syncthing

# CentOS/Rocky - use YUM repository
sudo rpm --import https://syncthing.net/release-key.txt
sudo tee /etc/yum.repos.d/syncthing.repo << 'EOF'
[syncthing-stable]
name=Syncthing Stable Channel
baseurl=https://apt.syncthing.net/rpm/stable/
gpgcheck=1
gpgkey=https://syncthing.net/release-key.txt
EOF
sudo dnf install -y syncthing

# Verify installation
syncthing --version

Running Syncthing as a Service

# Enable and start Syncthing for a specific user
sudo systemctl enable syncthing@yourusername
sudo systemctl start syncthing@yourusername
sudo systemctl status syncthing@yourusername

# Check logs
journalctl -u syncthing@yourusername -f

# Syncthing web UI is available at http://localhost:8384 by default
# It's only bound to localhost for security

Expose Web UI via Nginx (Optional)

# /etc/nginx/sites-available/syncthing
server {
    server_name sync.yourdomain.com;

    location / {
        proxy_pass http://localhost:8384;
        proxy_set_header Host $host;
        proxy_read_timeout 600s;
        proxy_send_timeout 600s;

        # Basic auth for added security
        auth_basic "Syncthing";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}
# Create password file
sudo htpasswd -c /etc/nginx/.htpasswd syncuser

sudo ln -s /etc/nginx/sites-available/syncthing /etc/nginx/sites-enabled/
sudo certbot --nginx -d sync.yourdomain.com
sudo systemctl reload nginx

# Configure Syncthing GUI to allow connections from Nginx
# Settings → GUI → GUI Listen Address: 127.0.0.1:8384
# Remove "Use HTTPS for GUI" since Nginx handles TLS

Device Pairing

Each Syncthing installation has a unique Device ID (fingerprint):

# Get your device ID
syncthing --device-id

# Or view in the web UI: Actions → Show ID

To pair two devices:

  1. Open the Syncthing web UI on Device A (http://localhost:8384)
  2. Go to Add Remote Device
  3. Enter Device B's Device ID
  4. Set a device name and optionally auto-accept folders
  5. Repeat on Device B, adding Device A's Device ID
  6. Both devices will show a pending connection request — accept it on each side
# Configure via CLI / config file
# Syncthing config is at: ~/.config/syncthing/config.xml (user)
# Or: /var/lib/syncthing/.config/syncthing/config.xml (service)

# Use the REST API to add a device
curl -X POST "http://localhost:8384/rest/config/devices" \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "deviceID": "XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX",
    "name": "backup-server",
    "addresses": ["dynamic"],
    "autoAcceptFolders": false
  }'

Folder Sharing and Configuration

# Add a folder via REST API
curl -X POST "http://localhost:8384/rest/config/folders" \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "documents",
    "label": "My Documents",
    "path": "/home/user/Documents",
    "type": "sendreceive",
    "devices": [
      {"deviceID": "REMOTE-DEVICE-ID"},
      {"deviceID": "ANOTHER-DEVICE-ID"}
    ],
    "rescanIntervalS": 3600,
    "fsWatcherEnabled": true
  }'

# Folder types:
# sendreceive - default, sync bidirectionally
# sendonly - send changes, don't receive (good for backups from client)
# receiveonly - receive changes, don't send (read-only mirror)
# receiveencrypted - encrypted-only copy (untrusted device)

Encrypted Folder Sharing

Send encrypted files to an untrusted device (no decryption key on that device):

# On the trusted device: add the untrusted device with an encryption password
# Web UI: Edit Folder → Sharing tab → Add device → set Encryption Password
# The untrusted device will sync encrypted blobs it cannot read

Versioning and Conflict Resolution

Configure file versioning per folder:

# Set versioning via API
curl -X PATCH "http://localhost:8384/rest/config/folders/documents" \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "versioning": {
      "type": "trashcan",
      "params": {
        "cleanoutDays": "30"
      }
    }
  }'

# Versioning types:
# trashcan - keep deleted files for N days (like Recycle Bin)
# simple - keep last N versions
# staggered - time-based retention (hourly/daily/weekly/monthly)
# external - run a custom script on each version

Staggered Versioning Config

<!-- In config.xml folder section -->
<versioning type="staggered">
    <param key="cleanInterval" val="3600"/>
    <param key="maxAge" val="31536000"/>  <!-- 1 year in seconds -->
</versioning>

Conflict resolution: Syncthing creates .sync-conflict-YYYYMMDD-HHMMSS-DEVICEID files when simultaneous edits occur. Review and merge them manually.

Ignore Patterns

Create .stignore in the root of each synced folder:

cat > ~/Documents/.stignore << 'EOF'
# Ignore system files
.DS_Store
Thumbs.db
desktop.ini

# Ignore temp and cache files
*.tmp
*.swp
*~
.cache

# Ignore build artifacts
node_modules
__pycache__
*.pyc
.git
dist/
build/
target/

# Ignore large media files (sync separately)
*.mkv
*.avi
*.iso

# Include specific subdirectory even if parent is ignored
!important-node-module/
EOF
# Common .stignore directives:
# //        - comment
# *         - matches any file
# **        - matches any path
# ?         - matches single character
# !pattern  - include (override previous exclusion)
# (?d)      - delete on other devices when ignored locally

Relay Servers and Discovery

When devices can't communicate directly (NAT, firewall), Syncthing uses relay servers:

# View relay status in web UI: Actions → Advanced → relaysEnabled
# Or check via API
curl -s "http://localhost:8384/rest/system/connections" \
  -H "X-API-Key: your-api-key" | python3 -m json.tool

# Run your own relay server
# Install syncthing-relaysrv
wget https://github.com/syncthing/relaysrv/releases/latest/download/relaysrv-linux-amd64.tar.gz
tar -xzf relaysrv-linux-amd64.tar.gz

./strelaysrv -listen=:22067 -pools=""

# Tell clients to use your relay
# Web UI: Settings → Connections → Sync Protocol Listen Address:
# Add: relay://your-server-ip:22067/?id=YOUR-DEVICE-ID

Docker Deployment

# docker-compose.yml
version: '3'

services:
  syncthing:
    image: syncthing/syncthing:latest
    container_name: syncthing
    environment:
      - PUID=1000
      - PGID=1000
    volumes:
      - /opt/syncthing/data:/var/syncthing
      - /data/sync:/sync  # Mount your sync directory here
    ports:
      - "8384:8384"    # Web UI
      - "22000:22000"  # Sync protocol TCP
      - "22000:22000/udp"  # Sync protocol QUIC
      - "21027:21027/udp"  # Local discovery
    restart: unless-stopped
    healthcheck:
      test: curl -fkLsS -m 2 127.0.0.1:8384/rest/noauth/health | grep -o '"OK"\|"ok"'
      interval: 1m
      timeout: 10s
      retries: 3
docker compose up -d
docker compose logs syncthing -f

Troubleshooting

Devices not connecting:

# Check firewall allows Syncthing ports
sudo ufw allow 22000/tcp
sudo ufw allow 22000/udp
sudo ufw allow 21027/udp

# Test direct connectivity from client
nc -z -v remote-server-ip 22000

# Check connection status
curl -s "http://localhost:8384/rest/system/connections" \
  -H "X-API-Key: your-api-key"

Sync stuck or not progressing:

# Check if folder is in sync error state
curl -s "http://localhost:8384/rest/db/status?folder=documents" \
  -H "X-API-Key: your-api-key"

# Force rescan
curl -X POST "http://localhost:8384/rest/db/scan?folder=documents" \
  -H "X-API-Key: your-api-key"

High CPU usage:

# Reduce rescan interval (default 3600s is fine, don't set to 0)
# Disable filesystem watcher if inotify limits are hit
echo "fs.inotify.max_user_watches = 204800" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Conclusion

Syncthing's decentralized design means there's no single point of failure, no subscription cost, and no third-party holding your data. With encrypted folder sharing, flexible versioning, and custom relay servers, it can handle everything from simple two-device sync to complex multi-server distributed file infrastructure. Its Docker availability and REST API make it straightforward to integrate into existing Linux server environments.