This document covers the Unifi Protect backup service deployment on the Dell R240 HA cluster with Pacemaker/Corosync clustering and shared NFS storage. This service automatically backs up all Unifi Protect camera footage to the Synology NAS for offsite retention.
/mnt/ha-shared/unifi-backups/
ghcr.io/ep1cman/unifi-protect-backup:latest
Configured in systemd service file:
UFP_USERNAME=backup # Local Protect user
UFP_PASSWORD=<password> # User password
UFP_ADDRESS=192.168.1.1 # Protect API endpoint
UFP_SSL_VERIFY=false # Disable SSL verification
The service backs up all event types:
Backups are organized hierarchically:
/mnt/ha-shared/unifi-backups/
└── {camera_name}/
└── {date}/
└── {timestamp} {detection_type}.mp4
Example:
/mnt/ha-shared/unifi-backups/G5 Bullet/2026-01-06/2026-01-06T11-58-22 smartDetectZone (person).mp4
Location: /etc/systemd/system/ha-unifi-backup.service
[Unit]
Description=Unifi Protect Backup
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=-/usr/bin/docker stop unifi-protect-backup
ExecStartPre=-/usr/bin/docker rm unifi-protect-backup
ExecStart=/usr/bin/docker run -d \
--name unifi-protect-backup \
-v /mnt/ha-shared/unifi-backups:/data \
-e UFP_USERNAME=backup \
-e UFP_PASSWORD=<password> \
-e UFP_ADDRESS=192.168.1.1 \
-e UFP_SSL_VERIFY=false \
-e RCLONE_RETENTION=365d \
--restart=unless-stopped \
ghcr.io/ep1cman/unifi-protect-backup:latest
ExecStop=/usr/bin/docker stop unifi-protect-backup
ExecStopPost=/usr/bin/docker rm unifi-protect-backup
[Install]
WantedBy=multi-user.target
Key features:
# On both nodes
sudo systemctl daemon-reload
sudo systemctl enable ha-unifi-backup.service
The backup service runs as a Pacemaker-managed resource for automatic failover:
# Create resource
sudo pcs resource create ha-unifi-backup systemd:ha-unifi-backup \
op monitor interval=30s timeout=60s \
op start timeout=120s \
op stop timeout=60s
# Colocate with NFS mount (CRITICAL)
sudo pcs constraint colocation add ha-unifi-backup with ha-nfs-mount
# Prefer thing-1
sudo pcs constraint location ha-unifi-backup prefers thing-1=100
Important: The colocation constraint ensures the backup service always runs on the same node as the NFS mount, preventing write failures.
Verify status:
sudo pcs status
Expected output:
* ha-unifi-backup (systemd:ha-unifi-backup): Started thing-1
The API requires a local Protect user (not your main UniFi account):
Access Protect:
Create Local User:
backupVerify User:
Detected cameras are automatically backed up. Current configuration:
To exclude specific cameras, add to systemd service:
-e IGNORE_CAMERAS="camera-id-1,camera-id-2" \
/mnt/ha-shared/unifi-backups/
All footage is stored on the Synology NAS via NFS, ensuring:
Default Settings:
Modify Retention:
Edit systemd service and add:
-e RCLONE_RETENTION=14d \ # Keep 14 days instead
Then reload and restart:
sudo systemctl daemon-reload
sudo pcs resource restart ha-unifi-backup
Estimate storage needs:
Per Camera:
Example:
Monitor Usage:
du -sh /mnt/ha-shared/unifi-backups/
du -sh /mnt/ha-shared/unifi-backups/*/
# Pacemaker status
sudo pcs status | grep ha-unifi-backup
# Systemd status
sudo systemctl status ha-unifi-backup
# Container status
docker ps | grep unifi-protect-backup
# Real-time logs
docker logs -f unifi-protect-backup
# Last 100 lines
docker logs --tail 100 unifi-protect-backup
# Search for errors
docker logs unifi-protect-backup 2>&1 | grep -i error
Successful Connection:
[INFO] Connecting to Unifi Protect...
[INFO] Found cameras:
[INFO] - 6939e400019df703e400043f: G5 Bullet
[INFO] Starting Tasks...
[INFO] Starting Downloader
[INFO] Starting Uploader
Download Activity:
[INFO] [event-id] Downloading event: event-id
[DEBUG] Camera: G5 Bullet
[DEBUG] Type: smartDetectZone (person)
[DEBUG] Start: 2026-01-06T11-54-36
[DEBUG] Duration: 225.973s
[DEBUG] Downloaded video size: 187.8MiBs
Upload Activity:
[INFO] [event-id] Uploading event: event-id
[DEBUG] Destination: local:/data/G5 Bullet/2026-01-06/2026-01-06T11-58-22 smartDetectZone (person).mp4
[DEBUG] Uploaded
Event metadata is stored in SQLite:
/mnt/ha-shared/unifi-backups/database/events.sqlite
Query events:
docker exec unifi-protect-backup sqlite3 /config/database/events.sqlite \
"SELECT * FROM events ORDER BY start DESC LIMIT 10;"
Symptom:
BadRequest: Request failed: https://192.168.1.1/api/auth/login - Status: 499 - Reason: unknown
Causes:
Solution:
sudo pcs resource restart ha-unifi-backupSymptom:
[ERROR] Connection refused to 192.168.1.1:443
Causes:
Solution:
# Test connectivity
ping 192.168.1.1
curl -k https://192.168.1.1/api/bootstrap
# Verify Protect is accessible
# Access https://192.168.1.1 in browser
# Check firewall
sudo firewall-cmd --list-all
Symptom: Container runs but no files in /mnt/ha-shared/unifi-backups/
Possible Causes:
Solution:
# Verify NFS mount
df -h | grep ha-shared
ls -la /mnt/ha-shared/unifi-backups/
# Check camera configuration in Protect
# Verify motion detection is enabled
# Create test event by walking in front of camera
# Check logs for download activity
docker logs unifi-protect-backup | grep Downloading
Symptom:
[ERROR] Permission denied: /data/
Cause: Container can't write to NFS mount
Solution:
# Fix permissions
sudo chown -R 911:911 /mnt/ha-shared/unifi-backups/
sudo chmod -R 755 /mnt/ha-shared/unifi-backups/
# Restart service
sudo pcs resource restart ha-unifi-backup
Symptom: Pacemaker shows service as "Stopped" or "Failed"
Debugging:
# Try starting manually
sudo systemctl start ha-unifi-backup
sudo systemctl status ha-unifi-backup
# Check for errors
journalctl -u ha-unifi-backup -n 50
# Verify docker is running
sudo systemctl status docker
# Check NFS mount
mount | grep ha-shared
Put thing-1 in standby mode:
sudo pcs node standby thing-1
Verify services move to thing-2:
sudo pcs status
# Should show: ha-unifi-backup (systemd:ha-unifi-backup): Started thing-2
Check container on thing-2:
ssh thing-2 'docker ps | grep unifi'
ssh thing-2 'docker logs unifi-protect-backup --tail 20'
Bring thing-1 back online:
sudo pcs node unstandby thing-1
Pacemaker monitors the ha-unifi-backup service every 30 seconds. If it fails, automatic failover occurs:
After failover, verify backup continuity:
# Check latest files
ls -lt /mnt/ha-shared/unifi-backups/G5\ Bullet/$(date +%Y-%m-%d)/ | head
# Verify no gaps in timestamps
# Events should continue without missing data
# Check logs for reconnection
docker logs unifi-protect-backup | grep "Websocket connection restored"
Critical Data:
/mnt/ha-shared/unifi-backups/ # Video footage
/mnt/ha-shared/unifi-backups/database/ # Event metadata (SQLite)
Configuration Files:
/etc/systemd/system/ha-unifi-backup.service
The Synology NAS should handle backups:
Option 1: Synology Hyper Backup
Option 2: Synology Cloud Sync
Option 3: rsync to External Location
# On Synology or backup server
rsync -av --delete \
/volume1/ha-cluster/unifi-backups/ \
/external/backup/location/unifi-backups/
To restore service on new servers:
/mnt/ha-sharedsudo pcs resource enable ha-unifi-backupAll footage and event history will be immediately available.
Limit backups to specific event types:
Edit systemd service and add:
-e DETECTION_TYPES="person,vehicle,package" \
Ignore specific cameras:
-e IGNORE_CAMERAS="camera-id-1,camera-id-2" \
Find camera IDs in logs:
docker logs unifi-protect-backup | grep "Found cameras"
Prevent bandwidth saturation:
-e DOWNLOAD_RATE_LIMIT=10 \ # 10 events per minute
Modify organization:
-e FILE_STRUCTURE_FORMAT="{event.start:%Y-%m-%d}/{camera_name}/{event.end:%H-%M-%S}.mp4" \
Result:
/mnt/ha-shared/unifi-backups/2026-01-06/G5 Bullet/11-58-22.mp4
Enable Apprise notifications for events:
-e APPRISE_NOTIFIERS="discord://webhook-url" \
Supported services: Discord, Slack, Pushover, Telegram, Email, etc.
All backup traffic between servers and Synology NAS uses 10GbE networking:
Typical per backup session:
Current configuration handles:
Protect User:
NFS Security:
Container Security:
Firewall Rules:
SSL Verification:
UFP_SSL_VERIFY=false)┌─────────────────────────────────────┐
│ Unifi Dream Machine │
│ 192.168.1.1 │
│ │
│ Unifi Protect │
│ └── G5 Bullet Camera │
│ └── Motion Events │
└──────────────┬──────────────────────┘
│ HTTPS API (443)
↓
┌──────────────────────────────────────┐
│ HA Cluster (Pacemaker) │
│ │
│ ┌─────────────┬─────────────┐ │
│ │ thing-1 │ thing-2 │ │
│ │ (Active) │ (Standby) │ │
│ │ │ │ │
│ │ Container │ Container │ │
│ │ (Running) │ (Ready) │ │
│ └──────┬──────┴──────┬──────┘ │
│ │ │ │
│ │ 10GbE NFS │ │
│ ↓ ↓ │
│ ┌──────────────────────────────┐ │
│ │ /mnt/ha-shared/ │ │
│ │ └── unifi-backups/ │ │
│ │ ├── G5 Bullet/ │ │
│ │ │ └── 2026-01-06/ │ │
│ │ │ └── *.mp4 │ │
│ │ └── database/ │ │
│ │ └── events.sqlite │ │
│ └──────────────────────────────┘ │
└──────────────┬───────────────────────┘
│ NFS
↓
┌──────────────────────────┐
│ Synology RS1221RP+ │
│ 192.168.1.246 │
│ │
│ 32GB RAM + 1TB Cache │
│ RAID 6 Storage │
│ 10GbE Network │
└──────────────────────────┘
Document maintained by: Josh Kenney
Last updated: January 10, 2026
Infrastructure: Dell R240 HA Cluster with Unifi Protect Backup