Skip to main content

Logging and Health Checks

Syncthing logs all events to the systemd journal. Knowing how to extract meaningful signals — sync completions, errors, connection events — is essential for maintaining a reliable sync mesh.

Learning Focus

Build actionable health checks from Syncthing's REST API and journal output that can be wired into cron, systemd timers, or monitoring tools like Prometheus.

Tool Snapshot
Log SourceCommandUse Case
Systemd journaljournalctl --user -u syncthingGeneral event stream
REST API /rest/system/statuscurl localhost:8384/rest/system/statusMachine-readable health
REST API /rest/eventscurl localhost:8384/rest/eventsStructured event stream
REST API /rest/db/statuscurl localhost:8384/rest/db/status?folder=IDPer-folder sync status

Reading Logs

read-logs.sh
# Last 100 lines
journalctl --user -u syncthing -n 100

# Since last boot
journalctl --user -u syncthing -b

# Follow in real time
journalctl --user -u syncthing -f

# Filter by log level (ERR and above)
journalctl --user -u syncthing -p err

# Search for specific events
journalctl --user -u syncthing | grep -E "Connected|Disconnected|conflict|error"

Setting Log Verbosity

Syncthing uses --logflags and environment variables to control verbosity:

verbose-launch.sh
# Extra verbose output for debugging (not for production)
STLEVEL=verbose syncthing serve --no-browser --logflags=3

# Suppress timestamps (useful when journald adds its own)
syncthing serve --no-browser --logflags=0

In the systemd unit, set environment:

override — verbose logging
[Service]
Environment=STLEVEL=verbose

REST API Health Checks

healthcheck-api.sh
# Get an API key first (from GUI: Actions → Settings → API Key)
STKEY="your-api-key-here"

# System status (version, uptime, memory)
curl -fs -H "X-API-Key: $STKEY" https://localhost:8384/rest/system/status \
--cacert ~/.local/share/syncthing/https-cert.pem | jq '{version:.version, uptime:.uptime, mem:.sys}'

# Per-folder sync status
FOLDER_ID="docs-sync"
curl -fs -H "X-API-Key: $STKEY" \
"https://localhost:8384/rest/db/status?folder=$FOLDER_ID" \
--cacert ~/.local/share/syncthing/https-cert.pem \
| jq '{state:.state, errors:.errors, need:.needBytes}'

# List connected devices
curl -fs -H "X-API-Key: $STKEY" \
https://localhost:8384/rest/system/connections \
--cacert ~/.local/share/syncthing/https-cert.pem \
| jq '.connections | to_entries[] | {id:.key, connected:.value.connected}'

Writing a Health Check Script

/usr/local/bin/syncthing-healthcheck.sh
#!/bin/bash
# Syncthing health check — exit 0 = healthy, exit 1 = unhealthy
set -euo pipefail

STKEY="${SYNCTHING_API_KEY:-}"
BASE="https://localhost:8384"
CERT="$HOME/.local/share/syncthing/https-cert.pem"

if [[ -z "$STKEY" ]]; then
echo "ERROR: SYNCTHING_API_KEY not set"
exit 1
fi

STATUS=$(curl -fs -H "X-API-Key: $STKEY" "$BASE/rest/system/status" --cacert "$CERT" 2>/dev/null) || {
echo "CRITICAL: Syncthing REST API not reachable"
exit 1
}

UPTIME=$(echo "$STATUS" | jq '.uptime')
echo "OK: Syncthing running — uptime ${UPTIME}s"

# Check all folders for error state
FOLDERS=$(curl -fs -H "X-API-Key: $STKEY" "$BASE/rest/config/folders" --cacert "$CERT" | jq -r '.[].id')
for FOLDER in $FOLDERS; do
STATE=$(curl -fs -H "X-API-Key: $STKEY" "$BASE/rest/db/status?folder=$FOLDER" --cacert "$CERT" | jq -r '.state')
if [[ "$STATE" == "error" ]]; then
echo "WARNING: Folder $FOLDER is in error state"
exit 1
fi
done

echo "OK: All folders syncing normally"
exit 0
chmod +x /usr/local/bin/syncthing-healthcheck.sh
export SYNCTHING_API_KEY="your-api-key"
/usr/local/bin/syncthing-healthcheck.sh

Scheduled Health Check with systemd Timer

/etc/systemd/system/syncthing-health.service
[Unit]
Description=Syncthing Health Check
After=syncthing@syncthing.service

[Service]
Type=oneshot
User=syncthing
Environment=SYNCTHING_API_KEY=your-api-key
ExecStart=/usr/local/bin/syncthing-healthcheck.sh
/etc/systemd/system/syncthing-health.timer
[Unit]
Description=Run Syncthing health check every 5 minutes

[Timer]
OnBootSec=60s
OnUnitActiveSec=5m
Unit=syncthing-health.service

[Install]
WantedBy=timers.target
sudo systemctl enable --now syncthing-health.timer
sudo systemctl list-timers | grep syncthing

Key Log Events to Monitor

Log PatternMeaningAction
conflict copySync conflict createdReview conflict file, investigate cause
ERROR: ... permission deniedFile permission issueFix ownership with chown
Stopping syncthingSyncthing shut downCheck systemd restart, investigate crash
Connected toNew peer connectionNormal operation
Disconnected fromPeer went offlineMonitor frequency — may indicate network issue
STUN errorNAT traversal failedVerify UDP port 22000 is open

What's Next