Purpose: What I wish I knew before starting this 44TB migration project.
TL;DR: Use rsync -s (--protect-args) and run rsync scripts ON THE SOURCE HOST, not through nested SSH. Spaces in paths are your enemy when using SSH as transport.
Symptom: Rsync completed successfully (exit code 0), but files went to the WRONG location.
Expected: /volume1/Public/Filmworks Backups/PFW Backup 008/
Actual: /volume1/Public/Filmworks/
This happened THREE TIMES before we figured it out. Each failure wasted ~12-24 hours.
Command from pulsedocker:
rsync -av --update \
root@192.168.67.9:'/mnt/user/Video/theia/Video/ARCHIVE/PFW Backup 008/' \
claudessh@192.168.67.20:'/volume1/Public/Filmworks Backups/PFW Backup 008/'
Why it failed: Nested SSH quoting - destination path parsed TWICE (local shell + remote rsync daemon). Space in "Filmworks Backups" got split during second parsing.
Tried double quotes, escaped spaces, nested quotes - ALL FAILED. Quoting worked for local shell but not for rsync protocol over SSH.
Theory: If directory exists, rsync won't misinterpret path.
Reality: Rsync STILL wrote to wrong location. Treating symptom, not cause.
Checked versions (3.1.2 vs 3.3.0) - both support --protect-args. Not a version issue.
Add -s flag (--protect-args)
Tells rsync "don't let remote shell split arguments at spaces"
Run rsync FROM source host, not through orchestrator
Eliminates nested SSH quoting entirely
# Script on Theia2 at /root/resume_008.sh
rsync -avs --update --progress \
'/mnt/user/Video/theia/Video/ARCHIVE/PFW Backup 008/' \
claudessh@192.168.67.20:'/volume1/Public/Filmworks Backups/PFW Backup 008/' \
| tee >(ssh claudessh@192.168.67.20 'cat > /volume1/Public/rsync_008_output.log')
Key: Source path is local (no SSH), only destination goes through SSH with -s protection.
rsync -avs --update --dry-run '/source/' user@host:'/dest/'
Red flag: If rsync tries to CREATE destination directory, path is wrong.
ssh user@host 'ls -la "/dest/path/" | head -20'
Don't wait hours/days to discover failure!
ssh user@host 'ls -la /volume1/Public/Filmworks/'
If this exists with your data, you've been bitten by quoting bug.
-s flag on source (10 min)15 minutes to avoid 60+ hours of waste
192.168.67.9 - Theia2 (source, Unraid)
192.168.67.20 - PulseFlashNAS (destination, Asustor)
192.168.67.25 - pulsedocker (orchestrator, Ubuntu)
Data flows: Theia2 → PulseFlashNAS directly (not through orchestrator)
Key quote from external AI consultation:
"Rsync over SSH involves TWO shells: local parses command, then remote (invoked by SSH) parses again. --protect-args tells rsync to treat entire argument as unit and not let remote shell split it."
This was the "aha!" moment - not a bug, expected shell behavior needing explicit prevention.
ssh -i ~/.ssh/id_theia2 root@192.168.67.9 "ps aux | grep rsync | grep -v grep"
ssh -i ~/.ssh/id_theia2 root@192.168.67.9 \
"ssh claudessh@192.168.67.20 'du -sh \"/volume1/Public/Filmworks Backups/PFW Backup XXX\"'"
ssh -i ~/.ssh/id_theia2 root@192.168.67.9 "pkill -f 'resume_XXX.sh'"
Multi-TB rsync over SSH with spaces in paths:
-s (--protect-args) - NON-NEGOTIABLE--update for resume capabilityThis saves days of wasted transfer time and hours of debugging.