Automate encrypted server backups with a cron job
Last updated: 2026-08-06
Back ups you have to remember to run don't happen. Cron does remember, and the Relayium CLI is built for that: a single non-interactive command that copies (or mirrors) a directory to another machine, verifies every file, and picks up where it left off if the network drops.
This guide covers scheduling relayium push and the incremental relayium sync from cron, the two transports you can point either one at, and the crontab lines to copy.
push vs sync: full copy or incremental mirror
Both push and sync move a directory to another machine and both are safe to run repeatedly, but they solve slightly different backup problems.
push sends an SSH or daemon-direct copy each time you run it — simple, and it even works against a bare server with no relayium installed via a tar fallback. sync instead keeps the destination as an incremental one-way mirror of the source: only changed files are re-sent, so a nightly sync of a large directory after the first run is fast. sync always needs relayium's native protocol on both ends — it has no tar fallback.
- Use push for a straightforward scheduled copy, especially to a server that might not have relayium installed.
- Use sync for a large or frequently-changing directory where re-sending everything every night would be wasteful.
- Both are per-file SHA-256 verified and resumable if interrupted.
Before you start
Everything below is the relayium CLI, so install it first if you haven't. On macOS or Linux, one command drops a prebuilt binary on your PATH:
curl -fsSL https://relayium.com/install.sh | sh
- Prefer to pick the file yourself, or on Windows? Grab a binary from the releases page — relayium.com/cli lists every install option (or go build -o relayium ./cmd/relayium if you have Go).
- relayium --version confirms it's installed. Skip this and the commands below just print 'command not found'.
Two transports: SSH or daemon-direct
Point either command at an SSH destination (scp-style, using your ~/.ssh/config) or, if the other machine is running relayium serve, straight at it over the daemon-direct protocol — no SSH needed.
# SSH destination — uses your existing SSH keys and config
relayium push ./data user@backup-server:/srv/backups/
# daemon-direct — the destination runs "relayium serve", no SSH required
relayium push ./data relayium://backup-server:9031
- Daemon-direct connections are pinned TLS 1.3 with trust-on-first-use, then pinned to that fingerprint on every run after.
- sync accepts the same two destination forms as push.
Schedule it with cron
What you need before step 1
- The CLI on this machine, and on the destination too if you plan to use sync. sync has no tar fallback.
- An SSH key with no passphrase, or a destination running relayium serve. cron has no agent and no terminal, so it cannot answer a passphrase prompt.
- A source directory that exists at the moment cron fires — not one on a network mount that is only there while you are logged in.
- Somewhere to write a log. A cron job whose output goes nowhere is a backup you will find out about when you need it.
Both push and sync are single, non-interactive commands, so they drop straight into a crontab. Point them at an SSH key with no passphrase (or an agent), and log the output so failures are visible:
# full copy every night at 2am — add to your crontab (crontab -e)
0 2 * * * relayium push -i ~/.ssh/backup_key ~/documents user@backup-server:/srv/backups/ >> ~/relayium-backup.log 2>&1
# incremental mirror every 15 minutes instead
*/15 * * * * relayium sync -i ~/.ssh/backup_key ~/documents user@backup-server:/srv/backups/ >> ~/relayium-sync.log 2>&1
Find out where relayium actually is. cron does not use your shell's PATH, and install.sh falls back to ~/.local/bin when /usr/local/bin is not writable — which is exactly the case cron cannot see.
command -v relayiumConfirm the key works with nobody at the keyboard. BatchMode=yes fails instead of prompting, which is what cron would do.
ssh -i ~/.ssh/backup_key -o BatchMode=yes user@backup-server trueRun the whole command by hand once, written exactly as cron will run it, absolute path included.
/usr/local/bin/relayium push -i ~/.ssh/backup_key ~/documents user@backup-server:/srv/backups/Only then add the schedule. Keep the absolute path and the redirect.
crontab -eAfter the first scheduled tick, read the log instead of assuming. This is the step people skip, and it is the one that would have told them.
tail -n 20 ~/relayium-backup.log
What a working setup looks like
relayium resolves to an absolute path you can paste into the crontab, and the BatchMode ssh check exits 0 without printing anything or asking for anything. A backup that only works from your interactive shell is not scheduled yet.
$ command -v relayium
/usr/local/bin/relayium
$ ssh -i ~/.ssh/backup_key -o BatchMode=yes user@backup-server true
$ echo $?
0- The command exits non-zero if any file fails its integrity check, so cron's mail-on-failure catches problems.
- An interrupted run simply resumes or catches up on the next scheduled run.
Mirroring deletions and real-time sync
By default sync only ever adds or updates files at the destination. Add --delete to make it a true mirror that also removes files the source no longer has — the receiving side must be explicitly listening with serve --allow-delete, or the deletions are silently skipped and reported back as denied. sync also refuses --delete outright if the source directory resolves to no files, so a typo in the source path can't wipe the destination.
If you'd rather not wait for cron's next tick, --watch keeps relayium sync running and re-syncs automatically a moment after any file under the source changes — a lightweight alternative to polling on a schedule.
- relayium sync ./data user@backup-server:/srv/backups/ --delete mirrors deletions (receiver needs serve --allow-delete).
- relayium sync ./data user@backup-server:/srv/backups/ --watch stays running and re-syncs on change instead of running once from cron.
When it doesn't work
Every one of these is invisible until you look at the log, which is why the log redirect is in the crontab line rather than being optional. The fifth is worse than invisible: it looks like success.
Symptom, check, fix
- The log says relayium: command not found, but the same command works in your shell.
tail -n 5 ~/relayium-backup.log # /bin/sh: relayium: command not foundcron runs with a minimal PATH, usually just /usr/bin:/bin. If install.sh could not write to /usr/local/bin it put the binary in ~/.local/bin, which cron will never find. Use the absolute path from command -v in the crontab line, or set PATH= on a line at the top of the crontab.
- The log shows the ssh connection being refused, or nothing after the first run.
ssh -i ~/.ssh/backup_key -o BatchMode=yes user@backup-server true # Permission denied (publickey).cron has no ssh-agent and no terminal, so a key with a passphrase can only hang or fail. Point -i at a passphrase-less key reserved for backups, and confirm with BatchMode=yes, which refuses to prompt rather than waiting for someone who is not there.
- sync runs cleanly but files deleted at the source are still on the destination.
grep -i deni ~/relayium-sync.logDeletion is a receiver-side opt-in. Without serve --allow-delete on the other end the deletions are skipped and reported back as denied, which is why the log has the answer and the exit code does not. Restart the receiver's listener with --allow-delete.
- sync refuses --delete outright.
relayium sync ~/documents user@backup-server:/srv/backups/ --delete # refusing --delete with an empty source: this would delete everything on the destination. Check the path(s).The source resolved to no files, so the mirror would have emptied the destination. That refusal is deliberate. Check the path for a typo, and check that anything mounted there is actually mounted at the time cron fires rather than only when you are logged in.
- The backup runs, exits 0, and is not what you think it is.
ssh user@backup-server command -v relayiumpush falls back to a plain tar stream over SSH when the remote has no relayium. Your files arrive, so nothing complains — but that path has no per-file SHA-256 verification and no resume, which are the two reasons to schedule this rather than scp. Install the CLI on the destination to get them back. sync does not have this failure mode because it has no fallback at all: it fails loudly instead.
Frequently asked questions
Does the backup server need relayium installed?
It depends on the command. push works either way: with relayium installed it uses the native protocol (resume + SHA-256 per file); without it, push falls back to a plain tar stream over SSH, so a bare server still works. sync always needs relayium's native protocol on the remote — there's no tar fallback for sync, so install it there first.
Is the backup encrypted and verified?
Yes. Every file is checked with a SHA-256 hash end to end, and pushing over SSH or daemon-direct means the bytes are already protected by that connection's encryption — nothing extra to configure.
What happens if the cron job is interrupted halfway through?
With relayium on both ends, the next scheduled run resumes partial files instead of resending everything. Pass --no-resume if you ever want a clean full re-send instead.
Can --delete accidentally wipe my destination?
sync refuses to run with --delete if the source directory contains no files, and the receiver has to be started with serve --allow-delete for deletions to take effect at all — otherwise they're skipped and reported back to you.
Do I need an account or does this cost anything?
No. The CLI is free and needs no account for push, pull, or sync — the transfer runs over your own SSH connection or a direct daemon connection, not through Relayium's servers.
Put your backups on a schedule you don't have to remember — encrypted, resumable, and free.
Get the CLI