Automated Rsync Backup from Synology NAS to USB via Proxmox LXC
An automated incremental contingency system using rsync between Synology DSM and an LXC container.
📌 Context and Architecture
đź”™ Main context: This guide is part of the architecture documented in the Infrastructure MOC.
Objective: Build an automated, local backup system that remains usable during an internet outage and incrementally copies the Dropbox and G-Drive directories from the Synology NAS—the source of truth—to an external drive.
Target hardware: A 320 GB external HDD formatted as exFAT for portability. If the server fails, the drive can be disconnected and read immediately by the primary workstation (Hackintosh).
Architecture: Synology NAS → Local network → Proxmox node → Privileged LXC → 320 GB USB HDD.
⚙️ Phase 1: Prepare the Source (Synology DSM)
To follow the principle of least privilege, the container uses a dedicated, restricted account instead of a DSM administrator account.
- Go to Control Panel > User & Group > Create.
- Credentials:
- User:
backupjd. - A unique, strong password stored outside the script.
- User:
- Shared-folder permissions: Grant Read only access exclusively to the
Drivefolder that contains the source data. - Application permissions: Ensure that the account is allowed to use SMB.
đź’˝ Phase 2: Persistently Mount the HDD on the Proxmox Host
Proxmox may assign a different device name after the USB drive is reconnected—for example, /dev/sdb may become /dev/sde. Mounting by UUID avoids depending on that dynamic name.
- Get the partition UUID:
blkid /dev/sde2 # Replace with the correct partitionRecord the alphanumeric value, for example 69A3-7677.
- Edit the filesystem table:
nano /etc/fstab- Add the mount rule at the end of the file:
UUID=69A3-7677 /mnt/backup_contingencia exfat defaults,nofail 0 0The nofail option is important: if the server starts while the USB drive is disconnected, Proxmox can continue booting instead of treating the missing mount as fatal.
- Reload systemd and mount the filesystems:
systemctl daemon-reload
mount -a📦 Phase 3: Create and Configure the LXC
The intermediary container needs elevated permissions to mount a network filesystem.
- Create the LXC:
- ID:
102(name:rsync-backup). - OS: Debian 12.
- Resources: 1 CPU core, 1024 MB RAM, DHCP networking.
- ⚠️ Critical: On the General tab, clear the
Unprivileged containeroption.
- ID:
- Enable network-filesystem support:
- With the LXC created but stopped, go to Options > Features.
- Enable SMB/CIFS. Without it, AppArmor blocks
mount.cifs.
- Bind-mount the host directory into the LXC:
Run this command on the Proxmox host, not inside the container:
pct set 102 -mp0 /mnt/backup_contingencia,mp=/mnt/usb_contingencia📜 Phase 4: Script and Automate the Backup Inside the LXC
- Start the LXC, open its console, and install the dependencies:
apt update && apt install rsync cifs-utils nano -y
mkdir -p /mnt/dsm_drive- Create the Bash script:
nano /root/backup.sh- Add the final script (
backup.sh):
#!/bin/bash
LOG_GENERAL="/var/log/backup_estado.log"
echo "========================================" >> $LOG_GENERAL
echo "Starting contingency backup: $(date)" >> $LOG_GENERAL
# echo_interval=60 and serverino keep the CIFS session responsive.
if mount -t cifs -o username=[YOUR_USER],password=[YOUR_PASSWORD],ro,vers=3.0,echo_interval=60,serverino //192.168.X.X/Drive /mnt/dsm_drive; then
echo "Connection established. Copying files..." >> $LOG_GENERAL
# Mirror Dropbox while tolerating I/O latency.
rsync -rtvh --delete --timeout=600 --log-file=/var/log/backup_archivos.log /mnt/dsm_drive/Dropbox/ /mnt/usb_contingencia/Dropbox/
# Mirror Google Drive while tolerating I/O latency.
rsync -rtvh --delete --timeout=600 --log-file=/var/log/backup_archivos.log /mnt/dsm_drive/G-Drive/ /mnt/usb_contingencia/G-Drive/
umount /mnt/dsm_drive
echo "Backup completed. Network share disconnected: $(date)" >> $LOG_GENERAL
else
echo "CRITICAL ERROR: Unable to connect to DSM." >> $LOG_GENERAL
exit 1
fiReplace the bracketed credentials before using the script and ensure the file remains readable only by root.
- Make the script executable:
chmod +x /root/backup.sh- Schedule the cron job to run every day at 1:00 a.m.:
crontab -eAdd this line at the end of the file:
0 1 * * * /root/backup.sh > /var/log/cron_backup.log 2>&1🛑 Troubleshooting Log
The following issues appeared while implementing the architecture.
-
Error:
mount error(1): Operation not permitted- Diagnosis: The container was created as unprivileged. The Linux kernel prevents it from mounting SMB/CIFS filesystems.
- Solution: Recreate the LXC with
Unprivileged containercleared.
-
Error:
mount error(13): Permission deniedeven though the credentials are correct.- Diagnosis (AppArmor): Proxmox blocked the mount operation. The kernel log (
dmesg | tail -n 10) showedapparmor="DENIED" operation="mount" fstype="cifs". - Solution: Enable SMB/CIFS under the LXC’s Options > Features, then restart the container.
- Diagnosis (AppArmor): Proxmox blocked the mount operation. The kernel log (
-
Error:
mount error(13): Permission deniedcaused by protocol negotiation.- Diagnosis: Debian 12 and Synology DSM negotiated incompatible SMB dialect settings.
- Solution: Add
vers=3.0to themount.cifsoptions.
-
Error:
rsync error: some files/attrs were not transferred (code 23)- Diagnosis: The
-aarchive option attempts to preserve Unix ownership and permissions. The exFAT destination cannot represent those attributes. - Solution: Replace
-avhwith-rtvhto copy recursively while preserving modification times and retaining verbose, human-readable output.
- Diagnosis: The
-
Error: After disconnecting and reconnecting the USB drive, mounting fails with
can't find in /etc/fstab.- Diagnosis: The kernel assigned a different device name; for example,
/dev/sdbbecame/dev/sde. - Solution: Obtain the UUID with
blkidand use it in/etc/fstab, as shown in Phase 2.
- Diagnosis: The kernel assigned a different device name; for example,
-
Error:
rsync: [sender] write error: Broken pipe (32)accompanied by repeatedcode 23failures.- Diagnosis: The CIFS session timed out while processing thousands of small files, such as files in Python virtual environments.
- Solution: Add
echo_interval=60,serverinoto the CIFS mount options and--timeout=600to thersynccommands.
-
Error:
rsync: [receiver] mkstemp ... failed: Invalid argument (22)- Diagnosis: exFAT does not support several characters that may appear in source filenames:
?,",|,<,>,*,:,\, and/. - Solution: Rename the affected source files and remove unsupported characters.
- Diagnosis: exFAT does not support several characters that may appear in source filenames: