Update #12 - Step-by-Step Breakdown of UFW DDNS Update Script
Date: May 11, 2025
Category: Automation / Firewall
Backlink: Update #11 β Syncthing UFW DDNS Cron Recovery & Long-Term Rule Persistence
Overview
This update documents the full working version of the update-syncthing-ufw.sh script, designed to automatically update UFW rules for Syncthing ports based on the current IP address of a DDNS hostname.
Script Location
/usr/local/bin/update-syncthing-ufw.shLog File
/var/log/update-syncthing-ufw.logFull Script Breakdown
#!/bin/bashStarts a bash shell script.
DDNS_HOST="<your-ddns-name"Specifies your DDNS hostname to resolve dynamically.
LOGFILE="/var/log/update-syncthing-ufw.log"Sets the path where all log entries will be stored.
PORTS=(
    "8384/tcp"
    "22000/tcp"
    "21027/udp"
)Defines an array of Syncthing-related ports (Web UI, sync port, and discovery port).
timestamp() {
    date "+%Y-%m-%d %H:%M:%S"
}Defines a helper function for timestamp formatting.
RESOLVED_IP=$(dig +short "$DDNS_HOST" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)Uses dig to resolve the IP for your DDNS and filter for valid IPv4 results.
if [[ -z "$RESOLVED_IP" ]]; then
    echo "$(timestamp) β Failed to resolve IP for $DDNS_HOST" | tee -a "$LOGFILE"
    exit 1
else
    echo "$(timestamp) π Resolved IP for $DDNS_HOST: $RESOLVED_IP" | tee -a "$LOGFILE"
fiLogs resolution status and aborts if the IP can't be resolved.
for PORT in "${PORTS[@]}"; do
    sudo ufw delete allow from any to any port "$PORT" comment 'Syncthing DDNS Access' > /dev/null 2>&1 || true
doneDeletes any prior rules with the comment 'Syncthing DDNS Access' silently. || true ensures the script continues even if a rule doesn't exist.
ALL_ADDED=trueTracks success status across all rule additions.
for PORT in "${PORTS[@]}"; doLoops over each port.
    if sudo ufw status | grep -q "$PORT.*$RESOLVED_IP"; then
        echo "$(timestamp) β³οΈ Rule already exists: $PORT from $RESOLVED_IP" | tee -a "$LOGFILE"If the rule already exists, log it as a no-op.
    elif sudo ufw allow from "$RESOLVED_IP" to any port "$PORT" comment 'Syncthing DDNS Access' > /dev/null 2>&1; then
        echo "$(timestamp) β
 Rule added: $PORT from $RESOLVED_IP" | tee -a "$LOGFILE"If the rule doesnβt exist, add it and log success.
    else
        echo "$(timestamp) β Failed to add rule: $PORT from $RESOLVED_IP" | tee -a "$LOGFILE"
        ALL_ADDED=false
    fi
doneIf adding fails, log an error and flag the batch as partially failed.
if $ALL_ADDED; then
    echo "$(timestamp) β
 All UFW rules successfully updated for Syncthing from $RESOLVED_IP" | tee -a "$LOGFILE"
else
    echo "$(timestamp) β οΈ Partial failure updating UFW rules for Syncthing from $RESOLVED_IP" | tee -a "$LOGFILE"
fiProvides a final summary log depending on success/failure of all rule additions.
Fixes & Adjustments Made
- 
Fixed Permission deniederrors by ensuring the script runs withsudowhen needed and logs are only written by root.
- 
Replaced silent failures with emoji-marked status outputs ( β,β,β οΈ,β³οΈ) for readability.
- 
Confirmed logs rotate daily via /etc/logrotate.d/update-syncthing-ufw.
Testing & Verification
- 
Manual execution verified with: 
sudo /usr/local/bin/update-syncthing-ufw.sh- 
UFW rules confirmed using: 
sudo ufw status verbose- 
Log output tail: 
sudo tail -n 20 /var/log/update-syncthing-ufw.log 
                
No Comments