Skip to main content

Backup Integration with Restic

Syncthing is a sync tool — if you delete a file, it disappears from all peers. For production data, sync must be combined with a backup solution. Restic is the natural complement: immutable snapshots, deduplication, and encryption.

Learning Focus

Build a layered data protection model: Syncthing for real-time availability across nodes, Restic for point-in-time recovery independent of sync propagation.

Tool Snapshot
ToolRoleHandles Deletion?EncryptionStorage
SyncthingReal-time replication❌ Propagates deletes✅ TLS in transitPeer devices
ResticSnapshot backup✅ Retains deleted files✅ AES-256 at restAny backend (S3, local, SFTP)

Architecture Overview

flowchart LR
subgraph Node A — Primary
DATA["/var/www/html/docs"] --> SYNC[Syncthing]
DATA --> RESTIC[Restic backup]
end
subgraph Node B — Replica
SYNC --> DATA2["/var/www/html/docs (replica)"]
end
subgraph Backup Storage
RESTIC --> S3[S3 / Backblaze B2]
end

Rule of thumb: Syncthing keeps you available, Restic keeps you recoverable.

Installing Restic

install-restic.sh
# Debian/Ubuntu
sudo apt install restic -y

# Verify
restic version

Initializing a Backup Repository

init-restic-repo.sh
# Local repository (for testing)
restic init --repo /mnt/backup/syncthing-docs

# S3 (recommended for production)
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"
restic init --repo s3:s3.amazonaws.com/your-bucket/syncthing-backup

Set a strong, stored password:

# Store password securely
echo "yourStrongR3sticPassword" > /etc/restic-password
chmod 600 /etc/restic-password

Running a Backup After Sync Settles

backup-synced-dir.sh
#!/bin/bash
# Backup the Syncthing-managed directory with Restic
set -euo pipefail

REPO="/mnt/backup/syncthing-docs"
PASSWORD_FILE="/etc/restic-password"
SOURCE="/var/www/html/docs"

# Wait for any in-progress sync to settle (optional — Syncthing is safe to backup live)
sleep 5

restic backup \
--repo "$REPO" \
--password-file "$PASSWORD_FILE" \
--tag syncthing \
--exclude "*.syncthing" \
--exclude ".stversions" \
"$SOURCE"

echo "Backup complete: $(restic snapshots --repo $REPO --password-file $PASSWORD_FILE --last | tail -n1)"

# Apply retention policy
restic forget \
--repo "$REPO" \
--password-file "$PASSWORD_FILE" \
--keep-hourly 24 \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--prune
note

Syncthing's .stversions directory contains internal version history files. Exclude it from Restic to avoid double-backing versioned data unless you specifically want it.

Automating with a systemd Timer

/etc/systemd/system/syncthing-backup.service
[Unit]
Description=Restic backup of Syncthing-managed directories
After=syncthing@syncthing.service

[Service]
Type=oneshot
User=syncthing
ExecStart=/usr/local/bin/backup-synced-dir.sh
StandardOutput=journal
StandardError=journal
/etc/systemd/system/syncthing-backup.timer
[Unit]
Description=Run Syncthing backup every 6 hours

[Timer]
OnBootSec=10m
OnUnitActiveSec=6h
Unit=syncthing-backup.service

[Install]
WantedBy=timers.target
sudo systemctl enable --now syncthing-backup.timer
# Verify next run
systemctl list-timers | grep backup

Restore Workflow

restore-from-restic.sh
REPO="/mnt/backup/syncthing-docs"
PASSWORD_FILE="/etc/restic-password"

# List snapshots
restic snapshots --repo "$REPO" --password-file "$PASSWORD_FILE"

# Restore a specific snapshot to a temporary directory
SNAPSHOT_ID="abc12345"
restic restore "$SNAPSHOT_ID" \
--repo "$REPO" \
--password-file "$PASSWORD_FILE" \
--target /tmp/restore-test

# Inspect the restored files
ls -la /tmp/restore-test/var/www/html/docs/

# Once verified, copy to the live Syncthing folder
rsync -av /tmp/restore-test/var/www/html/docs/ /var/www/html/docs/

Versioning Comparison

FeatureSyncthing VersioningRestic Snapshots
Max historyConfigurable (staggered or simple)Unlimited (retention policy)
Storage location.stversions on the same deviceSeparate encrypted repository
Encryption at rest❌ Not encrypted✅ AES-256
Recovery granularityPer-file versionsEntire snapshot or per-file
Protects against accidental delete✅ Yes (while policy applies)✅ Yes (until prune)
Protects against ransomware⚠️ Partial✅ Yes (immutable repo)

Common Mistakes

MistakeRiskFix
Relying only on Syncthing versioning for backupVersions stored on same device — at risk of disk failureUse Restic to off-device backup
Running backup while Syncthing is pausedStale data backed upPause sync only during maintenance, not backup windows
Skipping --prune in retention scriptRepository grows unboundedAlways include --prune with forget
Not testing restoresSilent backup corruption goes unnoticedRun restic check monthly and test restores quarterly

What's Next