Emergency server help: get in touch

Restic Backup for cPanel and DirectAdmin: Files, Databases, Retention

Back up cPanel and DirectAdmin servers with restic: home directories, database dumps via stdin, panel config, retention with forget/prune, and restore tests.

Published 8 min read

Short answer: Use restic as a second, off-server backup next to the panel’s own backups. Back up /home (sites and mail), stream a dump of every database straight into restic with --stdin-from-command, and include the panel’s configuration folders. Keep 7 daily, 4 weekly and 6 monthly snapshots with restic forget --prune, run restic check --read-data-subset weekly, and do a real test restore every month.

Applies to restic 0.17+ (tested 0.19.1); DirectAdmin 1.712 on AlmaLinux 9.8; paths checked on cPanel & WHM 11.138

We ran these commands on our lab server (AlmaLinux 9.8, DirectAdmin 1.712, restic 0.19.1) on 6 October 2026, with a test repository on the same server; the restic dump selection test used the same restic version on a scratch repository. The cPanel paths were checked on our cPanel lab (cPanel & WHM 11.138). Output below is from that run with names masked.

Where restic fits on a hosting server

cPanel and DirectAdmin backups are built to recreate an account: they carry the panel’s metadata, DNS zones, mail settings and databases in a format the panel can restore in one click. Restic is built for something else: fast, deduplicated, encrypted file snapshots that you can keep for months on cheap storage (S3-compatible buckets, SFTP, a restic REST server) and restore a single file from in seconds.

That makes them a good pair:

NeedUse
Recreate a whole account on a new serverPanel backup (cPanel backups, DirectAdmin Admin Backup/Transfer)
Restore one file, folder or mailbox from 3 weeks agorestic
Keep months of history without paying for full copiesrestic (deduplication)
A copy that ransomware on the server cannot deleterestic to an append-only or object-locked target

Our restic offsite backup script wraps the commands on this page into one scheduled job.

What to back up

Home directories (sites and mail)

Both panels keep sites and mail under /home/USER. On cPanel, mail is in /home/USER/mail; on DirectAdmin it is in /home/USER/imap (with Maildir for the account’s own mailbox), and sites are in /home/USER/domains. Back up /home as a whole, and exclude what you can rebuild:

cat > /root/restic-excludes.txt <<'EOF'
/home/virtfs
/home/*/.cache
/home/*/tmp
/home/*/.trash
/home/*/public_html/wp-content/cache
/home/*/domains/*/public_html/wp-content/cache
/home/*/admin_backups
/home/*/backups
EOF

/home/virtfs is cPanel’s jailed-shell mount tree; backing it up copies the system several times over. Also exclude panel backup folders, or you store every backup twice.

Databases

Never rely on copying /var/lib/mysql while MariaDB runs. Dump each database instead. restic 0.17 and later can run the dump itself and store its output, so nothing is written to local disk:

restic backup --tag db --stdin-filename bob_wp.sql \
  --stdin-from-command -- mariadb-dump --single-transaction --quick bob_wp

On DirectAdmin, root’s database credentials are in /usr/local/directadmin/conf/my.cnf; pass them with --defaults-extra-file. On cPanel, root normally has /root/.my.cnf. Loop over all databases:

for db in $(mariadb -N -e "SHOW DATABASES" | grep -Ev "^(information_schema|performance_schema|sys)$"); do
  restic backup --tag db --stdin-filename "$db.sql" \
    --stdin-from-command -- mariadb-dump --single-transaction --quick --routines --events "$db"
done

Panel configuration

These folders let you rebuild or audit the panel state. All of them existed on our labs:

PanelPaths
cPanel/var/cpanel/users, /var/cpanel/userdata, /var/cpanel/ssl, /var/named, /etc/userdomains, /etc/trueuserdomains, /etc/userdatadomains, /etc/valiases, /etc/vdomainaliases, /etc/vfilters
DirectAdmin/usr/local/directadmin/data, /usr/local/directadmin/conf, /usr/local/directadmin/custombuild/options.conf, /etc/virtual, /var/named, /etc/exim.conf
Both/etc (small, and saves you on firewall, SSH and cron settings)

Create the repository and run the first backup

Keep the repository password in a root-only file and the repository location in environment variables. For an S3-compatible bucket the repository looks like s3:https://s3.example.com/bucket/server1 plus AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY; for SFTP, sftp:backup@192.0.2.30:/srv/restic/server1.

umask 077
openssl rand -base64 32 > /root/.restic-pass
export RESTIC_REPOSITORY=sftp:backup@192.0.2.30:/srv/restic/server1
export RESTIC_PASSWORD_FILE=/root/.restic-pass
restic init

Store a copy of the password somewhere off the server (a password manager). restic’s own warning when you create a repository is that data is irrecoverably lost if you forget the password.

Then back up the files and one database. This is the output from our lab test (paths masked):

restic backup --tag files --exclude-caches -x /home/admin/domains/example.com/public_html
Files:        3778 new,     0 changed,     0 unmodified
Dirs:          476 new,     0 changed,     0 unmodified
Added to the repository: 105.714 MiB (36.185 MiB stored)
processed 3778 files, 104.362 MiB in 0:02
snapshot 3bae22c7 saved

restic backup --tag db --stdin-filename admin_wp1.sql --stdin-from-command -- mariadb-dump ...
Added to the repository: 115.121 KiB (23.332 KiB stored)
processed 1 files, 114.819 KiB in 0:00
snapshot 7f931ebc saved

Note the compression: about 106 MiB of WordPress files took 36 MiB in the repository. Later runs only upload changed data. For a full server, run it like this:

restic backup --tag files --exclude-caches -x \
  --exclude-file /root/restic-excludes.txt \
  /home /etc /var/named /var/cpanel        # cPanel
# DirectAdmin: /home /etc /var/named /usr/local/directadmin/data /usr/local/directadmin/conf

-x keeps restic on one filesystem, and --exclude-caches skips folders marked with a CACHEDIR.TAG file.

Retention with forget and prune

restic keeps every snapshot until you tell it otherwise. forget applies a policy per group of snapshots (by default host plus paths), and --prune then removes data no snapshot needs. Always look at a dry run first. From our lab:

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --dry-run
keep 1 snapshots:
ID        Time                 Host   Tags  Reasons           Paths           Size
7f931ebc  2026-10-06 01:15:11  host1  db    daily snapshot    /admin_wp1.sql  114.819 KiB
                                            weekly snapshot
                                            monthly snapshot

Because database snapshots use --stdin-filename, each database forms its own group, so the policy applies per database. When the output looks right, run it for real:

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

forget --prune deletes data permanently. Run the --dry-run version first after any change to tags, paths or the policy, and never run prune on the same repository from two servers at once.

Verify and test a restore

A backup you have never restored is a hope, not a backup. Check repository integrity weekly by reading a random part of the data:

restic check --read-data-subset=10%
read 10.0% of packfiles
no errors were found

Then restore something real every month. Our lab test restored the database dump into a separate folder:

restic restore latest --tag db --target /root/restore-test
restoring snapshot 7f931ebc of [/admin_wp1.sql] ... to /root/restore-test
Summary: Restored 1 files/dirs (114.819 KiB) in 0:00

head -2 /root/restore-test/admin_wp1.sql
-- MariaDB dump 10.19  Distrib 10.6.28-MariaDB, for linux-systemd (x86_64)

Useful restore patterns on a hosting server:

# list snapshots for one tag
restic snapshots --tag files

# restore one site folder from a given snapshot into a scratch path
restic restore 3bae22c7 --target /root/restore-test \
  --include /home/bob/public_html/wp-content/uploads

# newest dump of ONE database (select by path, not just by tag)
restic dump --path /bob_wp.sql latest /bob_wp.sql > /root/bob_wp.sql

Select database snapshots by --path. In our test, restic dump --tag db latest /bob_wp.sql failed with path "/bob_wp.sql" not found in snapshot as soon as another database had been backed up more recently, because latest picked the newest snapshot with that tag. Load the dump into a new database first and compare before you replace the live one.

Restore into a scratch folder or a new database name, compare, then copy over the live data. Fix ownership after file restores (chown -R bob:bob on cPanel; on DirectAdmin check the original owner and group, which vary by folder).

Schedule it

Run backups nightly from root’s cron or a systemd timer, with forget and prune weekly and a check after that. A minimal cron layout:

# /etc/cron.d/restic  (times in server local time)
15 2 * * *  root  /usr/local/sbin/restic-nightly.sh   >> /var/log/restic.log 2>&1
45 4 * * 0  root  /usr/local/sbin/restic-weekly.sh    >> /var/log/restic.log 2>&1

Run them at low priority (nice -n 19 ionice -c3) so customers do not notice, and alert on failure: restic exits with a non-zero code when a backup fails. Our backup verify script can check that the newest snapshot is recent.

Common problems

  • Backups are huge: panel backup folders, /home/virtfs or cache folders are included. Check the exclude file and restic stats latest.
  • Repository locked: a previous run was interrupted. Make sure no restic process is running, then restic unlock.
  • Database dump is empty: the dump command failed but the snapshot was saved. Check the size in restic snapshots and test the dump command by hand.
  • Restore has the wrong owner: restic restores numeric IDs. On a new server with different UIDs, fix ownership with chown.

Official documentation: restic documentation · restic: Backing up (stdin and commands) · restic: Removing snapshots (forget/prune)

Related: Restic Backup Script for Offsite Backups · Backup Verify Script · WHM Backups S3: Reliable Remote Backups and Test Restores · DirectAdmin Backups S3: Reliable Admin, Reseller and User Backups · mariadb-dump vs mysqldump: modern backup commands and wildcard database dumps

See also: JetBackup 5 Restore in WHM: Accounts, Files, Databases, Email · JetBackup 4 to 5 Migration: The 5.2.11 Stepping Stone · cPanel restorepkg and pkgacct: Backup and Restore from CLI

Frequently asked questions

Can restic replace cPanel or DirectAdmin backups?

Not fully. Restic stores files and dumps, not panel accounts. Keep panel backups for whole-account restores and use restic for long history and granular restores.

How do I back up MySQL databases with restic?

Dump each database with mariadb-dump and stream it in with restic backup –stdin-from-command and –stdin-filename. Do not copy /var/lib/mysql while the server runs.

What retention should a hosting server use?

A common start is 7 daily, 4 weekly and 6 monthly snapshots. Adjust to your terms of service and storage budget.

How often should I run restic check?

Weekly with –read-data-subset (for example 10%), plus a real test restore every month.

Does restic encrypt backups?

Yes. Every repository is encrypted with its password; without the password the data cannot be read or recovered.

Maintenance record

This guide changes servers, data or security settings, so we re-check it against current versions on a fixed schedule. Take a backup or snapshot before you start.

Maintained by
srvScripts editorial team
Supported versions
restic 0.17+ (tested 0.19.1); DirectAdmin 1.712 on AlmaLinux 9.8; paths checked on cPanel & WHM 11.138
Last full review
Next review

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.