KingDezigns — NAS08 → NAS16 Sync Setup Summary v2.0

📅 Updated May 18, 2026 🖥 NAS08 (192.168.150.35) → NAS16 (192.168.150.40) ⚙️ OpenMediaVault / Raspberry Pi OS 🔧 rsync + NFSv4 + HTML Email Report
The goal

Mirror the Public folder from NAS08 to NAS16, copying only files that have changed. The sync must be lightweight enough for Raspberry Pi hardware, non-destructive (no deletes on NAS16), and scheduled via the OMV Task Scheduler. After every run, an HTML email report is sent summarizing what transferred, what folders were affected, and any errors.

Source: NAS08 — 192.168.150.35 Destination: NAS16 — 192.168.150.40 ~225,000 files / ~983 GB NFSv4 file share mount HTML email report

NAS16 pulls from NAS08 (rather than NAS08 pushing) so the heavier rsync process runs on the machine with more RAM (16GB vs 8GB), leaving NAS08 as a passive file server during the sync.

Folder paths
S Source — NAS08
/mnt/kingdezigns08/Public/

NFS share mounted on NAS16 via fstab at boot. Mount verified as non-empty before rsync runs.

D Destination — NAS16
/export/kingdezignsnas-16/Public/

Local path on NAS16. Script verifies directory exists before writing.

NAS08-only items (copied on first run)
16 - Documents/
Savings Card Forms.pdf
kingdezigns08.nas

All three copied successfully on first sync. kingdezigns08.nas included intentionally.

Permanently excluded
/mnt/kingdezigns08/Public/.Trash-1000/

System trash folder generated by NAS08's desktop environment. Never needed in backup. Excluded via --exclude='.Trash-1000/' in rsync flags.

No longer appears in logs or emails.

Key decisions
Pull vs Push

NAS16 pulls from NAS08 via the mounted NFS share. rsync runs entirely on NAS16 to keep NAS08 load minimal — NAS08 is passive during the sync window.

NFSv4 File Share vs SSH

NFS share used instead of SSH. Drive already mounted via fstab on NAS16 — no SSH keys or remote execution needed. NFS maps users by UID. Both machines have rufusking as UID 1000 so permissions resolve correctly over the mount.

No --delete flag

Files on NAS16 that do not exist on NAS08 are left untouched. NAS16 is a backup, not a strict mirror. This protects NAS16-only files from accidental deletion.

--update flag (not --checksum)

rsync skips files where the NAS16 copy is newer than NAS08. This is lightweight (uses timestamps, not file hashing) and protects any edits made directly on NAS16.

Schedule: Every other day at 2:30 AM via OMV Task Scheduler. NAS08 runs its own nas16-backup.sh at 2:00 AM (finishes ~2:05 AM). The 25-minute buffer prevents overlap on heavy nights.

Setup steps performed
1 Created script directory on NAS16
sudo mkdir /usr/scripts/nas
sudo chown rufusking:users /usr/scripts/nas

/usr/scripts already existed. /nas subfolder created manually on NAS16. chown required after sudo mkdir — ownership defaults to root otherwise.

Directory created and ownership set successfully.

2 Copied script from Linux PC to NAS16
scp /path/to/nas08_to_nas16_sync.sh rufusking@192.168.150.40:/usr/scripts/nas/

File transferred successfully.

3 Set executable permission on NAS16
sudo chmod +x /usr/scripts/nas/nas08_to_nas16_sync.sh

Run directly on NAS16 (not via remote SSH). Makes the script executable by the OMV scheduler.

Permission set. Script ready to run.

4 NFS export updated on NAS08 — subtree_check → no_subtree_check
# Changed in OMV UI → Services → NFS → Shares (all four shares)
# Then reloaded on NAS08:
sudo exportfs -ra

# Then remounted on NAS16 to pick up the new export options:
sudo umount /mnt/kingdezigns08
sudo mount /mnt/kingdezigns08

subtree_check was causing intermittent Permission Denied errors on 02 - Photos, 08 - Taxes, and 16 - Documents during scheduled overnight runs. no_subtree_check is the modern recommended default for private NFS setups.

All three folders now accessible. Permission errors resolved.

5 Fixed log directory ownership on NAS16
sudo chown -R rufusking:users /var/log/nas-sync/

Log directory was created by root during the first automated OMV run. Script now self-corrects ownership at startup so this never needs to be done manually again.

Log writing works cleanly. Self-healing ownership check added to script.

6 OMV Scheduler entry added on NAS16
Command : /usr/scripts/nas/nas08_to_nas16_sync.sh
Schedule: 30 2 */2 * *   (2:30 AM every other day)

Scheduled and confirmed running.

Script — final state
Location on NAS16
/usr/scripts/nas/nas08_to_nas16_sync.sh
Log output
/var/log/nas-sync/nas08_to_nas16_YYYY-MM-DD.log
Log rotation
Logs older than 30 days deleted automatically
rsync flags
--archive          Preserve permissions, timestamps, symlinks, owner/group
--update           Skip files where NAS16 copy is newer (protects NAS16 edits)
--human-readable   Sizes in KB/MB/GB
--itemize-changes  One structured line per transferred file — used for folder activity parsing
--stats            Summary totals at end of each run
--exclude          Excludes .Trash-1000/ from all operations
Safety features
NFS mount check     Waits up to 30s for NFS share to be fully responsive before starting
Source empty check  Aborts if NAS08 share appears empty — prevents accidental wipe of destination
Dest check          Confirms NAS16 folder exists before writing
Smart lock file     Stores PID in lock file; auto-clears stale locks if process is no longer running
Log ownership fix   Self-corrects /var/log/nas-sync/ ownership on every startup
Exit code           Returns rsync exit code so OMV scheduler can detect failures
Email report sections
Header/banner       SUCCESS / WARNING / FAILED status with color coding
Stats tiles         Files scanned, transferred, new files, data moved, duration
Source/dest info    IPs, paths, transfer rate, total source size
Folder Activity     Collapsed by default — folders with changes show file count,
                    folders with errors show the error message, no-activity runs
                    show "all files up to date"
Full rsync log      Collapsed by default — complete raw output available on demand
Email recipient
rufus.king@kingdezigns.com
Troubleshooting log
T1 Permission Denied on 02 - Photos, 08 - Taxes, 16 - Documents
Error

rsync: [sender] opendir "/mnt/kingdezigns08/Public/02 - Photos" failed: Permission denied (13)

Investigation: ACLs confirmed correct on NAS08 (rufusking:rwx present on all affected folders and subfolders). UIDs matched on both machines (UID 1000). Folders readable manually via NAS16 terminal. Error only appeared during scheduled overnight runs.

Root cause: subtree_check in the NFS export config on NAS08 was causing intermittent access failures for folders with ACL-based permissions and mixed ownership (some owned by www-data via Nextcloud). subtree_check forces NFS to validate every file access against the export tree — this check fails intermittently on first access after an idle period, especially overnight.

Fix: Changed all four NFS shares on NAS08 from subtree_check to no_subtree_check via OMV UI. Reloaded exports with sudo exportfs -ra. Remounted share on NAS16. All three folders accessible on next run.

Resolved — no Permission Denied errors since fix applied.

T2 tee: Permission Denied on log file
Error

tee: /var/log/nas-sync/nas08_to_nas16_2026-05-17.log: Permission denied

Root cause: /var/log/nas-sync/ was created by root during the first automated OMV run. Running the script manually as rufusking couldn't write to a root-owned directory.

Fix: sudo chown -R rufusking:users /var/log/nas-sync/. Script updated to self-correct ownership on every startup — checks if the log directory owner matches the running user and auto-chowns if not.

Resolved — script is now self-healing for this condition.

T3 Stale lock file blocking manual runs
Error

ERROR: Lock file exists at /tmp/nas08_to_nas16.lock. Another sync may still be running. Exiting.

Root cause: Script was killed mid-run during testing, leaving the lock file behind. Original lock logic just checked for file existence with no way to distinguish a live run from a stale one.

Fix: Lock file now stores the script's PID. On startup, if a lock file exists the script checks whether that PID is still running. If not, it removes the stale lock and continues with a warning in the log.

Resolved — stale locks are now self-clearing.

T4 Folder Activity section showing 0 updated despite files transferring

Root cause: Original folder parser relied on xfr# markers from rsync's --progress flag. When --progress was removed (to clean up captured output), those markers disappeared and the parser never incremented folder counts. Switching to --verbose didn't help because verbose output only shows directory names, not individual files.

Fix: Replaced --verbose with --itemize-changes, which outputs a structured prefix line for every transferred file regardless of size (e.g. >f+++++++++ 02 - Photos/2020/12/photo.jpg). Parser updated to detect lines starting with >f and extract the top-level folder name.

Resolved — folder activity now correctly shows file counts per folder.

NAS08 NFS export reference

All four shares updated to no_subtree_check on May 18, 2026. The /export root entries are OMV auto-generated read-only entries — leave them as-is.

ShareNetworksKey Options
/export/kingdezigns-all .100 .110 .120 .150 rw, no_subtree_check, insecure, crossmnt
/export/kingdezigns08-secure .100 .110 .120 .150 rw, no_subtree_check, insecure, crossmnt
/export/kingdezigns-public .100 .110 .120 .150 rw, no_subtree_check, insecure, crossmnt
/export/HomeAssistantBackups .150 only rw, no_subtree_check, insecure, crossmnt
/export (root) .100 .110 .120 .150 ro, root_squash, subtree_check — OMV auto-generated, do not edit

Note: duplicate 192.168.100.0/24 entry for /export root exists in OMV config — pre-existing, harmless, clean up in OMV UI when convenient.

NAS08 nightly task timeline
TimeDeviceScriptNotes
12:00 AM NAS08 /usr/scripts/zfs/nas08_zfs_report.sh Daily ZFS health report email.
2:00 AM NAS08 & NAS16 /usr/scripts/omv/nas16-backup.sh Pre-existing backup script. NAS16 finishes ~1 min, NAS08 ~5 min. Runs every 3 days.
2:30 AM NAS16 /usr/scripts/nas/nas08_to_nas16_sync.sh NAS08 → NAS16 Public folder sync. 25-min buffer after NAS08 backup finishes.
3:00 AM (Sun) NAS08 /usr/scripts/zfs/nas08_zfs_scrub.sh Weekly ZFS scrub. Sundays only.
TBD TBD Future maintenance tasks Drive health checks, log cleanups, etc. — to be added later.
Lessons learned
LessonDetail
subtree_check causes intermittent NFS permission failures On folders with ACL-based or mixed ownership, subtree_check can fail the export tree validation intermittently — especially after idle periods overnight. no_subtree_check is the safe modern default for private home networks.
NFS client cache must be cleared after export changes Running exportfs -ra on the server isn't enough. The NFS client (NAS16) must unmount and remount to pick up the new export options. Without this, the old subtree_check behavior persists.
ACL permissions and NFS UIDs are separate concerns Files can have correct ACLs (rufusking:rwx) but still be blocked over NFS if the UID mapping fails. Always verify UIDs match on both machines with id username before assuming ACL issues.
sudo operations reset directory ownership Any sudo mkdir or sudo mount can leave directories owned by root. Scripts that write to those directories will fail with Permission Denied when run as a regular user. Always chown after sudo directory operations.
Lock files should store PIDs, not just exist A bare touch lock file can't distinguish a live run from a stale one left by a killed process. Storing the PID and checking if it's still running makes lock files self-healing.
--itemize-changes is the right flag for parsing file transfers --progress generates xfr# markers but is noisy. --verbose only lists directories. --itemize-changes gives one clean structured line per transferred file (>f prefix) that's easy to parse reliably regardless of file size.
Pull is safer than push for backups Running rsync on the destination keeps the source device (NAS08) passive and low-load during the sync window.
Schedule buffer matters Running the sync immediately after another backup script risks overlap on heavy nights. A 25-30 min buffer between jobs keeps things clean.
File count is larger than expected when blocked folders open up Initial estimate was ~16,000 files. Actual count after Photos/Taxes/Documents became accessible was ~225,000 files across ~983 GB. rsync handled this without issue.
Network map — items to update
ItemDetail
New script on NAS16 /usr/scripts/nas/nas08_to_nas16_sync.sh — document in NAS16 script inventory
New log location on NAS16 /var/log/nas-sync/ — add to log monitoring notes. 30-day auto-rotation.
OMV Scheduler — NAS16 Task added: 30 2 */2 * * running the sync script
NFS exports changed on NAS08 All four shares updated to no_subtree_check in OMV. Document in NAS08 config notes.
NAS08 → NAS16 data flow NAS08 Public folder now syncing to NAS16 Public every other day at 2:30 AM. 225,000 files / 983 GB in scope.
OMV duplicate export entry (cleanup pending) 192.168.100.0/24 appears twice for the /export root in NAS08's exports. Harmless but should be cleaned up in OMV UI when convenient.