Your Mail-in-a-Box Backup Strategy is probably Backwards
Most people running Mail-in-a-Box do backups the wrong way. They configure the mail server to push backups to remote storage. This seems logical: the server has the data, so it should send it somewhere safe, right?
Wrong.
Push-based backups are a security liability and a reliability nightmare. If your mail server gets compromised, the attacker now has credentials to your backup destination. They can wipe your backups before you even notice the breach. If your mail server is overloaded or goes down, your backup doesn't happen. You've created a single point of failure.
If you're backing up to a NAS or another server you control, the correct approach is to pull backups from that location, not push from your mail server.
Why Pull-Based Backups Are Superior (When You Control the Destination)
Security: Your mail server never has write access to your backup storage. Even if compromised, an attacker can't touch your backups. The NAS holds the SSH keys and initiates the connection. The mail server is just serving files.
Reliability: Your NAS controls the backup schedule. If the mail server is busy handling email, it doesn't matter. The NAS will pull the data when it's ready.
Centralization: One place manages all your backup schedules across multiple servers. Want to back up your mail server, web server, and database? The NAS orchestrates everything from a single schedule configuration.
Simplicity: No complex coordination between systems. The NAS pulls, verifies, and stores. Done.
When Pull-Based Doesn't Work
Object storage like S3, Backblaze B2, or Wasabi doesn't give you SSH access or the ability to run scripts. You can't "pull" from S3 because there's no server to initiate the connection. For these destinations, you're stuck with push-based backups. The mail server must have credentials and push data out.
This is where you need to weigh the tradeoffs. Object storage is convenient and cheap, but you're accepting the security risk that a compromised mail server can delete your backups. Some services offer object locking or versioning to mitigate this, but it's not foolproof.
If you have a NAS or another server you control, pull-based is always superior. That's what we're covering here.
The Implementation
Mail-in-a-Box uses duplicity for encrypted backups, storing them in /home/user-data/backup/. The encrypted folder contains the actual backup data. Our strategy: let the NAS pull these files via rsync over SSH.
Here's the core script:
#!/bin/bash
# Pull duplicity backups from mail server daily
MAIL_SERVER="root@<mail_in_a_box_ip>"
SSH_KEY="/absolute_path_for_your_user/.ssh/id_ed25519_mailbox_root"
NAS_BACKUP_ROOT="/mnt/storage/mailserver-backups" # or wherever you want
TEMP_DIR="/tmp/mail-duplicity-staging"
# Create staging directory
mkdir -p "${NAS_BACKUP_ROOT}/duplicity-daily"
mkdir -p "${TEMP_DIR}"
# Pull duplicity backups to staging
rsync -avz --delete \
-e "ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no" \
"${MAIL_SERVER}:/home/user-data/backup/" \
"${TEMP_DIR}/"
if [ $? -ne 0 ]; then
echo "Failed to pull backups"
exit 1
fi
# Verify encrypted folder exists and isn't empty
if [ ! -d "${TEMP_DIR}/encrypted" ]; then
echo "Encrypted folder missing"
exit 2
fi
if [ -z "$(ls -A ${TEMP_DIR}/encrypted)" ]; then
echo "Encrypted folder is empty"
exit 3
fi
# Sync to final destination
rm -rf "${NAS_BACKUP_ROOT}/duplicity-daily"/*
rsync -a "${TEMP_DIR}/" "${NAS_BACKUP_ROOT}/duplicity-daily/"
if [ $? -ne 0 ]; then
echo "Failed to sync to final destination"
exit 4
fi
# Cleanup
rm -rf "${TEMP_DIR}"
Why This Works
Staging Directory: We pull to a temp directory first, then sync to the final location. This is atomic. If the pull fails midway, your existing backup remains untouched. No partial, corrupted backups.
Verification: We explicitly check that the encrypted folder exists and contains data. Most backup scripts skip this. They assume success if rsync exits 0, but rsync will happily sync an empty directory. Your backups could be failing silently for weeks.
Cleanup: The temp directory gets wiped after each run. No disk space accumulation, no stale data hanging around.
Dedicated SSH Key: Use a separate SSH key just for this backup operation. If something goes wrong, you revoke one key, not your entire NAS access.
Setup Steps
On the NAS:
Generate a dedicated SSH key:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_mailbox_root
Copy the public key to your mail server's root authorized_keys:
ssh-copy-id -i ~/.ssh/id_ed25519_mailbox_root.pub root@your-mail-server
Save the script to /usr/local/bin/nas-pull-duplicity-daily.sh, make it executable:
chmod +x /usr/local/bin/nas-pull-duplicity-daily.sh
Scheduling on Synology NAS:
Synology DSM doesn't use traditional cron. Instead, use the Task Scheduler in the Control Panel:
- Open Control Panel > Task Scheduler
- Create > Scheduled Task > User-defined script
- General tab: Name it "Mail-in-a-Box Backup Pull", select root user
- Schedule tab: Set daily execution at 3 AM (or whenever you prefer)
- Task Settings tab: User-defined script field, enter:
/usr/local/bin/nas-pull-duplicity-daily.sh - Save
The task will now run automatically on your schedule.
For other NAS systems with traditional cron:
Add to crontab:
0 3 * * * /usr/local/bin/nas-pull-duplicity-daily.sh
This runs at 3 AM daily. Adjust as needed.
The Alternative: Push-Based with After-Backup Hooks
If you're using object storage or insist on keeping the push-based approach for other reasons, Mail-in-a-Box supports custom after-backup scripts. You can hook into the backup process and execute additional commands after the built-in backup completes.
Create /home/user-data/backup/after-backup on your mail server:
#!/bin/bash
rsync -avz /home/user-data/backup/ backup-user@nas:/backups/mailserver/
Make it executable:
chmod +x /home/user-data/backup/after-backup
Mail-in-a-Box will execute this after each backup run. But remember: this approach gives your mail server write access to your backup destination. If the mail server is compromised, so are your backups.
For S3-compatible storage, you'd use something like:
#!/bin/bash
aws s3 sync /home/user-data/backup/ s3://your-bucket/mailserver-backups/
Same security concern applies. The mail server has credentials to write (and delete) from your S3 bucket.
What About Restores?
With pull-based backups, restores are straightforward. Your NAS has the duplicity archives. To restore:
# On the mail server
export PASSPHRASE="your-encryption-passphrase"
duplicity restore file:///home/user-data/backup/encrypted /path/to/restore
Or pull the encrypted folder from your NAS back to the mail server first, then restore from there. Either way works.
The Bottom Line
Stop pushing backups when you don't have to. Pull them instead. Your mail server should be treated as untrusted. It's exposed to the internet, handling potentially malicious email, running complex software. Your NAS sits safely behind your network, managing backups for everything.
One orchestrates. The other serves data. That's the right architecture.
This approach works for my use-case. Your environment might differ. The script is intentionally simple to make the concept clear. Production deployments should add proper logging, alerting, and regular restore testing. But the core principle remains: pull backups when you control the destination, don't push from untrusted systems.