Loading...
Home
Explore
Contact
Sign in
Security, Hardening & Backups

Ubuntu Nightly Website Backups with Restic, rclone & Cron

A client lost an entire site—files, database, everything. This guide shows Australian site owners how to back up multiple Ubuntu websites nightly at 2am with restic, rclone, and cron so recovery is routine, not a crisis.

Fixwebnode Support
Fixwebnode Support
10 min read 25 views
Ubuntu Nightly Website Backups with Restic, rclone & Cron

If you run websites on an Ubuntu server and still rely on hope instead of tested backups, this guide is for you. By the end you will have restic, rclone, and cron backing up multiple site roots (and optional databases) every night at 2am to cheap object storage—set once, then verify on a schedule.

Last year a client lost a full site. Everything. Gone. Host panel snapshots were empty, the developer copy was months old, and restore meant rebuilding from scratch. We now back up about twenty websites automatically every night at 2am for roughly a dollar a month in object storage using restic, rclone, and cron on Ubuntu. For remote website support across Australia, Fixwebnode helps owners lock this in without turning backup into another unpaid side job.

Why automatic nightly backups matter after a total site loss

Manual zip downloads fail when you are busy. Provider “backups” often exclude databases, custom paths, or the week you actually need. A total loss usually arrives as a blank document root, a wiped VPS, a bad deploy, or ransomware—not a polite warning. Restic gives encrypted, deduplicated snapshots. rclone ships those snapshots to off-server storage. cron runs the job at 2am while traffic is low. Together they turn “everything gone” into “restore last night’s snapshot.”

This walkthrough assumes Ubuntu Server 22.04 or 24.04 with sudo access, sites under paths such as /var/www, and outbound HTTPS allowed for your storage provider. Work is fully remote: SSH, packages, and a restore test.

How do I set up restic and rclone nightly website backups on Ubuntu in Australia?

Install restic and rclone, point rclone at object storage, initialise an encrypted restic repository through that remote, then run a small backup script from cron at 02:00 in your server timezone (use Australia/Sydney or your state zone). Verify with a dry-run restore and check logs the next morning so a silent failure does not wait until the next disaster.

SymptomQuick fixWhen to call Fixwebnode
Cron ran but no new snapshotCheck script exit code, restic unlock, path permissionsMultiple sites, mixed stacks, or unclear logs
rclone auth / 401 errorsRe-run rclone config, refresh keys, test lsdKeys rotated by host or shared team access
Cannot restore or repo lockedCheck locks, run check, restore to a temp pathProduction down and you need a clean cutover

Common issues with restic, rclone, and cron website backups

These are the failures we see after someone “set backups once” and never looked again.

  • Silent cron success with zero new snapshots — mail is off, the script returns 0 after a partial path miss, or restic never runs because the environment in cron lacks PATH or the password file.
  • rclone remote authentication failures — API keys rotated, wrong endpoint, or bucket region mismatch; uploads die after local snapshot work.
  • Repository locks and failed restores under pressure — a killed job left a lock, or nobody ever practised restore so the first real restore is during an outage.
  • Wrong 2am because of timezone drift — server stays on UTC; “2am” is afternoon local time in Australia, colliding with peak traffic or deploys.

Issue 1 — Cron “succeeds” but no restic snapshot appears

Symptoms: grep CRON /var/log/syslog shows the job, yet restic snapshots lists nothing new. Sites still have no off-box copy.

Step 1 — Confirm the job and capture output

sudo grep -i backup /var/log/syslog | tail -n 50
sudo crontab -u root -l
ls -la /var/log/site-backup.log

Step 2 — Run the script in a clean cron-like environment

sudo env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
 HOME=/root \
 bash -x /usr/local/bin/backup-sites.sh 2>&1 | tee /tmp/backup-debug.log

Step 3 — Fix typical causes

  1. Ensure the restic password file is readable only by root: sudo chmod 600 /root/.restic-password.
  2. Export the same variables the script needs (RESTIC_REPOSITORY, RESTIC_PASSWORD_FILE, RCLONE_CONFIG) inside the script—not only in your interactive shell.
  3. Make the script executable: sudo chmod 750 /usr/local/bin/backup-sites.sh.
  4. Fail hard on errors: start the script with set -euo pipefail so a missing path does not look like success.

Step 4 — Verify

sudo restic -r rclone:offsite:sites-backup snapshots --password-file /root/.restic-password | tail

If logs still lie or twenty vhosts each have different owners, book remote help rather than guessing under load.

Issue 2 — rclone cannot authenticate to storage

Symptoms: restic errors mentioning rclone, HTTP 401/403, or rclone lsd fails while local disk still has data.

Step 1 — Test the remote alone

rclone listremotes
rclone lsd offsite: -vv

Step 2 — Repair config

rclone config
# update access key, secret, endpoint, and bucket
rclone mkdir offsite:sites-backup
rclone touch offsite:sites-backup/.write-test && rclone deletefile offsite:sites-backup/.write-test

Step 3 — Point restic at the fixed remote

export RESTIC_REPOSITORY="rclone:offsite:sites-backup"
export RESTIC_PASSWORD_FILE="/root/.restic-password"
restic snapshots

Re-create keys in the storage console if a former staff member still has the old pair. When billing accounts, buckets, and production SSH are tangled, Fixwebnode can separate them remotely without exposing long-lived keys in chat logs carelessly.

Issue 3 — Locks, corruption fears, or first restore fails

Symptoms: repository is already locked, restic check reports errors, or restore produces an empty tree when the site is already down.

Step 1 — Inspect locks (only if no backup is running)

restic -r rclone:offsite:sites-backup list locks --password-file /root/.restic-password
# If a stale lock remains after a confirmed dead process:
restic -r rclone:offsite:sites-backup unlock --password-file /root/.restic-password

Step 2 — Integrity check

restic -r rclone:offsite:sites-backup check --password-file /root/.restic-password

Step 3 — Practise restore to a temporary path (not over live files)

sudo mkdir -p /var/tmp/restore-test
sudo restic -r rclone:offsite:sites-backup restore latest \
 --target /var/tmp/restore-test \
 --password-file /root/.restic-password \
 --include /var/www/example.com
sudo ls -la /var/tmp/restore-test/var/www/example.com | head

If the site is offline and you need a cutover plan (web root, database dump, DNS, TLS), stop improvising on the live path and get a specialist on the session.

Issue 4 — “2am” is wrong for Australia

Symptoms: Jobs fire at midday local time; CPU spikes during business hours; logs show UTC stamps you misread.

Step 1 — Set timezone

timedatectl
sudo timedatectl set-timezone Australia/Sydney
# or Australia/Melbourne, Australia/Brisbane, Australia/Perth, Australia/Adelaide
timedatectl

Step 2 — Confirm cron schedule after the change

date
sudo crontab -l

Use 0 2 * * * only after the zone is correct. For multi-state fleets, document each server’s zone instead of assuming one “Australia time.”

Install restic and rclone on Ubuntu

Use distribution packages first; upgrade restic from the official binary only if you need a newer feature set.

Step 1 — Update and install

sudo apt update
sudo apt install -y restic rclone cron curl ca-certificates
restic version
rclone version

Step 2 — Optional: refresh restic self-update (if appropriate for your policy)

sudo restic self-update

Confirm cron is enabled:

sudo systemctl enable --now cron
systemctl is-active cron

Configure rclone remote storage

Pick durable object storage (S3-compatible, B2, or similar). Keep credentials off the web root.

Step 1 — Interactive remote

sudo rclone config

Create a remote named offsite, choose your provider, paste keys, set endpoint if required, then quit.

Step 2 — Restrict config permissions

sudo chmod 600 /root/.config/rclone/rclone.conf
sudo chown root:root /root/.config/rclone/rclone.conf
rclone lsd offsite:
rclone mkdir offsite:sites-backup

Initialise the restic repository

Step 1 — Password file

sudo install -m 600 /dev/null /root/.restic-password
sudo nano /root/.restic-password
# one long random line only, no trailing spaces

Generate a strong secret if needed:

openssl rand -base64 48 | sudo tee /root/.restic-password >/dev/null
sudo chmod 600 /root/.restic-password

Step 2 — Init repo through rclone

sudo restic -r rclone:offsite:sites-backup init --password-file /root/.restic-password

Store a copy of the password in an offline password manager. Without it, snapshots are unrecoverable by design.

Backup script for multiple websites

Back up document roots every night. Add database dumps if your sites are dynamic.

Step 1 — Optional database dump directory

sudo mkdir -p /var/backups/db-dumps
sudo chmod 700 /var/backups/db-dumps

Example MySQL/MariaDB dump loop (adjust user and socket auth to your setup):

sudo tee /usr/local/bin/dump-site-dbs.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
OUT=/var/backups/db-dumps
STAMP=$(date +%F)
# List DB names you own; do not dump system schemas blindly in shared hosts
for db in site1 site2 site3; do
 mysqldump --single-transaction --routines --triggers "$db" \
 | gzip -c > "$OUT/${db}_${STAMP}.sql.gz"
done
# keep dumps 3 days locally; restic holds history offsite
find "$OUT" -type f -name '*.sql.gz' -mtime +3 -delete
EOF
sudo chmod 750 /usr/local/bin/dump-site-dbs.sh

Step 2 — Main backup script

sudo tee /usr/local/bin/backup-sites.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export RESTIC_REPOSITORY="rclone:offsite:sites-backup"
export RESTIC_PASSWORD_FILE="/root/.restic-password"
export RCLONE_CONFIG="/root/.config/rclone/rclone.conf"

LOG=/var/log/site-backup.log
exec >>"$LOG" 2>&1
echo "==== $(date -Is) backup start ===="

if [[ -x /usr/local/bin/dump-site-dbs.sh ]]; then
 /usr/local/bin/dump-site-dbs.sh
fi

# Add every site root you must keep. Exclude caches and huge throwaway trees.
restic backup \
 /var/www \
 /var/backups/db-dumps \
 /etc/nginx \
 /etc/apache2 \
 /etc/letsencrypt \
 --exclude=/var/www/*/wp-content/cache \
 --exclude=/var/www/*/node_modules \
 --exclude=/var/www/*/vendor/cache \
 --tag websites \
 --tag nightly

# Retention: adjust to your recovery needs
restic forget --prune \
 --keep-daily 7 \
 --keep-weekly 4 \
 --keep-monthly 6 \
 --tag nightly

echo "==== $(date -Is) backup ok ===="
EOF
sudo chmod 750 /usr/local/bin/backup-sites.sh

Step 3 — First manual run

sudo /usr/local/bin/backup-sites.sh
sudo restic -r rclone:offsite:sites-backup snapshots --password-file /root/.restic-password
sudo tail -n 100 /var/log/site-backup.log

Schedule cron for 2am and log rotation

Step 1 — Root crontab

sudo crontab -e

Add:

0 2 * * * /usr/local/bin/backup-sites.sh

Step 2 — Logrotate so logs cannot fill the disk

sudo tee /etc/logrotate.d/site-backup >/dev/null <<'EOF'
/var/log/site-backup.log {
 weekly
 rotate 12
 compress
 missingok
 notifempty
 create 640 root root
}
EOF

Step 3 — Verify scheduling

sudo crontab -l
date
sudo systemctl status cron --no-pager

Verification checklist (do this before you “forget it forever”)

  1. Confirm a new snapshot ID after a manual run.
  2. Restore one small site tree to /var/tmp/restore-test and compare file counts.
  3. Restore one database dump and import into a non-production database name.
  4. Confirm object storage size and billing alerts so a runaway retain policy cannot surprise you.
  5. Document repository path, password location, and remote name in your operations notes—not in the web root.
sudo restic -r rclone:offsite:sites-backup stats --password-file /root/.restic-password
sudo restic -r rclone:offsite:sites-backup check --password-file /root/.restic-password

When DIY is enough vs when to book Fixwebnode

DIY is enough when you have root SSH, a short list of static or simple PHP sites, working object-storage keys, and time to complete one successful restore test. The steps above are enough for a careful owner or in-house admin.

Book Fixwebnode when any of these apply: production is already down; you manage many vhosts, containers, or mixed nginx/Apache stacks; database replication or staging cutover is involved; cron has been “fine” for months with no restore drill; or you need a second pair of eyes on retention, encryption keys, and offsite layout. Fixwebnode works as a direct specialist provider for remote website support—not a freelance marketplace. Geography and remote coverage are listed on the service areas page for Australian operators who want clear reach without shopfront theatre.

Talk to Fixwebnode about hardening your backup routine

A lost site teaches the same lesson every time: snapshots you have never restored are a story, not a plan. If you want restic, rclone, and cron installed, scheduled at 2am, logged, and restore-tested on Ubuntu—or you already have failures in the log and need a clean path back—start a conversation with the team via website repair and support Australia. Bring SSH access notes and a list of site roots; we will focus on durable nightly backups you can actually use when something disappears again.

Share this article
Fixwebnode Support
Fixwebnode Support

Hey there!
I am your assistant for Fixwebnode. Ask about our services, quotes, packages, orders, or how to get support.
While you wait
What’s your name and best email? We’ll reply even if you leave.