TrueNAS to UNAS Pro: An Append-Only Backup Story
I have a TrueNAS server and a UNAS Pro on my local network. I wanted a daily, append-only backup from the former to the latter. Simple, right?
Not quite. Here’s the full story of what I learned.
The Setup
Two boxes on a flat LAN:
- TrueNAS — Has an encrypted dataset. SMB share exposed.
- UNAS Pro — Runs UniFi’s NAS OS. Has an encrypted share called
Backups.
The constraints I set for myself:
- Append-only — files are written once and never deleted
- Run on TrueNAS — push from TrueNAS to UNAS, not the other way
- LAN-only, no encryption needed — plaintext SMB over local network is fine
Why This Isn’t Trivial
The UNAS Pro runs a locked-down OS. There’s no SSH, no rsync server, no ZFS replication endpoint. You can’t run arbitrary scripts on it. That eliminates all the clean TrueNAS-native approaches (ZFS send/recv, rsync over SSH).
What the UNAS does support is SMB. So the approach becomes: mount the UNAS share on TrueNAS as a CIFS filesystem, rsync data into it, unmount. All driven by a TrueNAS Cron Job.
The Script
After some iteration, here’s the final script:
#!/bin/bash
exec >> /var/log/unas-backup.log 2>&1
echo "=== $(date) backup start ==="
set -euo pipefail
SRC="/mnt/dataset-name/" # trailing slash matters
MNT="/mnt/unas-backup"
DEST="$MNT/truenas/my-backup"
SHARE="//unas-pro.local/Backups"
CRED="/root/.smb/unas.cred"
if [ -z "$(ls -A "$SRC" 2>/dev/null)" ]; then
echo "Source empty or locked, aborting."
exit 1
fi
mount -t cifs "$SHARE" "$MNT" \
-o credentials="$CRED",vers=3.0,uid=0,gid=0,iocharset=utf8
mkdir -p "$DEST"
rsync -a --ignore-existing --info=stats2 "$SRC" "$DEST/"
umount "$MNT"
echo "=== $(date) backup done ==="
The --ignore-existing flag is the key to append-only behavior: once a file exists on the destination, rsync never touches it again. If you want changed files updated (but still never deleted), drop that flag.
One-Time Setup
Store the UNAS SMB credentials in a root-only file:
mkdir -p /root/.smb
cat > /root/.smb/unas.cred <<'EOF'
username=YOUR_UNAS_USER
password=YOUR_UNAS_PASSWORD
EOF
chmod 600 /root/.smb/unas.cred
Create a stable mountpoint:
mkdir -p /mnt/unas-backup
Then register the script as a Cron Job in TrueNAS: System → Advanced → Cron Jobs → Add, run as root, daily at 3 AM.
The Bugs I Hit
1. The Space in the Path
My dataset had a space in its path. In the first version of the script, I’d written the path with a backslash escape:
SRC="/mnt/My\ Dataset/"
Inside double quotes, the backslash is literal. The script was trying to access a directory with a literal \ in its name. The ls -A guard caught this and exited 1.
Fix: quote the path, don’t escape the space inside quotes.
SRC="/mnt/My Dataset/"
A space in a ZFS dataset name is legal but will bite you in every script forever. Worth keeping in mind.
2. The EFAULT Error That Wasn’t Helpful
When the script failed from cron, TrueNAS reported:
[EFAULT] CronTask "/root/scripts/unas-backup.sh" exited with 1 (non-zero) exit status.
That’s all the information you get — TrueNAS records the exit code but not the stderr. The fix was two-fold:
- Add
exec >> /var/log/unas-backup.log 2>&1at the top so everything, including stderr, goes to a log file - Add
set -xtemporarily to trace each command
Run the script manually first before trusting the cron schedule.
3. SMB Version Mismatch
If vers=3.0 in the mount options doesn’t work, the UNAS OS may want a different SMB protocol version. Try vers=3.1.1 or vers=2.1.
4. The Encrypted Dataset Guard
If the TrueNAS dataset is locked at backup time (e.g., after a reboot before you enter the passphrase), the script sees an empty directory. The ls -A guard catches this and aborts rather than backing up nothing.
The Tradeoffs You Accept
This approach is simple but has real limitations:
- No snapshot history — This is file-level copy, not ZFS replication. No atomicity, no integrity checking.
- Renamed files become duplicates — Append-only means a renamed file is backed up as new; the old file never gets cleaned up.
- Unbounded growth — Plan disk headroom on the UNAS accordingly. If you later want history without unbounded growth, a versioning tool like restic or borg pointed at the mounted share is the upgrade path.
- Encryption at rest only — When TrueNAS reads files over SMB, they’re decrypted; when written to the UNAS, the UNAS re-encrypts at rest. The wire is plaintext (fine for my LAN).
One Improvement
Add logging with set -x during initial testing so every command is traced to the log. Remove it once everything’s stable. If the cron job ever fails, you’ll have a log file with the exact error instead of the unhelpful “exit status 1” from TrueNAS.
The Takeaway
You can get reliable daily backups from TrueNAS to a locked-down appliance like the UNAS Pro using just SMB and rsync. The trick is to run the script on TrueNAS, mount the UNAS share locally, and treat it as a filesystem. It’s not as elegant as ZFS replication, but it works, it’s maintainable, and the append-only behavior is a deliberate choice for archival data.