Skip to content

How to Back Up a Linux Server: Files, Databases and an Off-site Copy with restic

5 min read

Applies to: Debian 13 and Ubuntu 24.04 and 26.04 with MariaDB 11.8 or MySQL 8.4; restic 0.16.4 (Ubuntu 24.04), 0.18 (Debian 13, Ubuntu 26.04) and 0.19.1 (EPEL for AlmaLinux 9)

To back up a Linux server, dump the databases to files, then copy those dumps and your important folders (/etc, the web roots, /home, /root) to another machine, on a schedule, keeping several older versions. A backup that stays on the same server doesn’t protect you from a disk failure, a hacked account or a mistaken rm. This guide builds that with standard tools and restic, then shows how to restore.

1. Decide what to back up

  • Configuration: /etc (web server, PHP, SSH, firewall, certificates in /etc/letsencrypt).
  • Websites and app data: /var/www, /srv, /home, and /root (scripts, .my.cnf).
  • Databases: as dumps, not the raw files in /var/lib/mysql, which can be inconsistent while the server runs.
  • Scheduled jobs and mail: /var/spool/cron and mail folders if the server hosts mail.
  • Skip caches, /tmp, /proc, /sys and anything you can reinstall. A list of installed packages is enough: apt-mark showmanual > /root/packages.txt.

2. Dump the databases

Put the database login in /root/.my.cnf (chmod 600) so it isn’t on the command line, then:

mariadb-dump --single-transaction --routines --events --databases shopdb | gzip > /var/backups/db/shopdb.sql.gz

On MySQL the commands are mysqldump and mysql (we checked mysqldump Ver 8.4.11). --single-transaction gives a consistent copy of InnoDB tables without locking the site. For PostgreSQL use pg_dump per database. Test the restore once: in our test, zcat shopdb.sql.gz | mariadb recreated the dropped database with its rows.

3. A quick local archive with tar

tar -czf /backup/files-$(date +%F).tar.gz --exclude=/var/www/site/cache /etc /var/www

tar prints Removing leading `/' from member names, which is normal. To restore one file into a separate folder:

tar -xzf /backup/files-2026-09-30.tar.gz -C /tmp/restore var/www/site/p1.html

This is fine before a risky change, but it is still on the same server. For regular backups, send copies elsewhere.

4. Off-site, encrypted and versioned with restic

restic stores encrypted, deduplicated snapshots, so a daily run only uploads what changed. It can write to another server over SFTP, to S3-compatible storage and more. Install it with sudo apt install restic (Debian, Ubuntu) or from EPEL on AlmaLinux.

On the backup server, create a user (here backup) and add the web server root’s SSH public key to its ~/.ssh/authorized_keys (see set up SSH keys): restic needs to log in without a password prompt for automatic backups. Then, on the web server, create the repository:

echo 'a-long-random-password' > /root/.restic-pass
chmod 600 /root/.restic-pass
restic -r sftp:backup@backup.example.com:/srv/restic/web01 --password-file /root/.restic-pass init

restic warns that losing the password means the data is lost for good. Keep a copy of it somewhere other than the server.

A backup script, /usr/local/sbin/server-backup.sh (chmod 700), that we ran successfully with restic 0.16.4 and MariaDB 11.8:

#!/bin/bash
set -euo pipefail
umask 077
export RESTIC_REPOSITORY="sftp:backup@backup.example.com:/srv/restic/web01"
export RESTIC_PASSWORD_FILE="/root/.restic-pass"

# 1. Dump each database to a file (login details in /root/.my.cnf)
mkdir -p /var/backups/db
for db in $(mariadb -N -e "SHOW DATABASES" | grep -Ev "^(information_schema|performance_schema|sys)$"); do
  mariadb-dump --single-transaction --routines --events --databases "$db" | gzip > "/var/backups/db/$db.sql.gz"
done

# 2. Send files and dumps to the repository
restic backup /etc /var/www /home /root /var/backups/db --exclude "/var/www/*/cache"

# 3. Keep 7 daily, 4 weekly and 6 monthly snapshots, delete the rest
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

umask 077 matters: without it the dumps were created readable by every user. Run it every night at 02:30 with a file /etc/cron.d/server-backup:

30 2 * * * root /usr/local/sbin/server-backup.sh >> /var/log/server-backup.log 2>&1

5. Check and restore

restic snapshots                                   # list backups
restic ls latest /var/www/site                     # browse a snapshot
restic restore latest --target /tmp/restore --include /var/www/site/index.html
restic check                                       # verify the repository

Restore into a separate folder, compare, then copy back what you need. A backup you have never restored is only a hope: try a full restore of one site and one database to a test server now and then. A wrong password gives Fatal: wrong password or no key found.

Other options

If you would rather have an engineer set up and test backups for you, see server management or hire an expert.

Official documentation: restic and mariadb-dump.

Related services

KVM VPS hosting

NVMe SSD and full root access, with Free Basic Managed Support.

Unmanaged dedicated servers

full root access and free IPMI KVM, with Free Basic Managed Support.

Linux server management

hardening, patching, monitoring and automation for Ubuntu, Debian, RHEL and AlmaLinux.

Was this answer helpful?

Still stuck? Open a ticket