HIP has no "take a snapshot" button: the one panel action that touches the disk wipes it. Here is how to build your own file and database backup that lives elsewhere and survives losing the server.
HIP has no "take a snapshot" button: the only panel action that touches the disk is a reinstall, and it wipes everything. So backing up a HIP server is entirely your job: you make the copies with tools on the server and keep them somewhere else. This guide covers making the data consistent before a copy, pulling files and databases, why restic and borg exist, running the backup on a schedule with a systemd timer, and confirming that the copy actually restores.
In short. There are no snapshots in the HIP panel; the backup is on your side. Before a copy run
sync, or better briefly stop the app and database, or take a dump with the engine's own tool. Pull files withtar(one-off) orrsync -aAX(regular) to another machine; dump databases withpg_dumpormysqldumpand rotate by N days. The default tool isrestic: it encrypts and deduplicates on its own, stores copies over SFTP or in object storage, and runs from a systemd timer. Follow the 3-2-1 rule and test the restore once a month.
First things first: the HIP panel has no snapshot feature. You cannot take a disk image with one click and roll back the same way. The only panel action that touches the disk is a reinstall (Rebuild), and it does not save anything - it wipes the system, files, databases and settings (see How to reinstall the OS on a HIP server).
The conclusion is simple: backups of a HIP server are made only on your side, with tools running on the server itself, writing out to somewhere else. The rest of this guide is how to build that so it runs on its own and actually restores.
A snapshot is a point-in-time image of the whole disk: the system, files, databases, settings, all as they were at the moment of capture. Hypervisors and some providers' panels offer snapshots; HIP does not. Even where a snapshot exists, it sits next to the server and is lost together with it.
A backup is an independent set of your data saved elsewhere: another server, object storage, a disk at home. It is not tied to the HIP server and survives anything that happens to the server (a reinstall, a deletion, a billing or account problem).
Roughly: a snapshot means "roll the whole server back to last night". A backup means "get me this file or this database from last Wednesday, even if the server is gone". On HIP only the second option exists, and the rest of this guide is about it.
Snapshot | Backup | |
|---|---|---|
What it is | image of the whole disk at a point in time | separate copy of selected data |
Where it lives | next to the server, on the provider or hypervisor | elsewhere: another server, storage, local |
In the HIP panel | no | you build it yourself |
Survives losing the server | no | yes |
What you can pull out | only the whole disk | individual files, individual databases |
Protects against | a bad upgrade, a broken migration | losing the server, data corruption, a week-old mistake, ransomware |
A backup pulls files as they are at the moment it runs. If the database is mid-transaction and the app is mid-log-write, the copy contains a half-written state. Most databases (PostgreSQL, MySQL with the InnoDB engine) recover from that on startup using their journal, but do not rely on it, especially for a file-level copy of the database.
The minimum is to flush what the OS holds in RAM to disk:
sync
The command returns once the buffers are written. There is no output on success.
Where you can, briefly stop the app and database, take the copy, then start them again:
systemctl stop myapp
systemctl stop postgresql
sync
# run the backup, wait for it to finish
systemctl start postgresql
systemctl start myapp
If a stop is not acceptable, capture the database as a dump rather than as files: the engine exports the data in a consistent form (covered separately below), and let restic or rsync pick up the finished dump file instead of the live database files.
For a one-off copy of some directories, tar collects everything into a single compressed archive:
tar czf /root/backup-$(date +%F).tar.gz --exclude='/var/www/*/cache' /etc /root /home /var/www
c create an archive, z compress with gzip, f to the named file--exclude skips a directory you do not want in the copy (cache, temp files)/etc (system and service configs), the app directory, /home (user data)$(date +%F) puts the date in the file name, like 2026-09-10Then move the archive off the server: scp /root/backup-*.tar.gz you@backuphost:/srv/backups/. While it only sits on the server, it is not a backup.
For regular sync of the whole server to another machine, use rsync, which copies only what changed:
rsync -aAX --delete \
--exclude={"/proc/*","/sys/*","/dev/*","/run/*","/tmp/*","/var/tmp/*","/var/cache/*","/var/lib/lxcfs","/swapfile","/swap.img","/lost+found"} \
/ backup@backuphost:/srv/backups/web01/
-a archive mode: preserves permissions, owners, timestamps, symlinks-A carries POSIX ACLs, -X extended attributes--delete makes a mirror: it removes on the target what is no longer on the server. Without it, deleted files pile up in the copy--exclude={...} virtual and temporary directories that are pointless (and harmful) to copy: /proc, /sys, /dev are kernel interfaces, not files; /tmp, /var/cache are transient; /swapfile or /swap.img is the swap file (the name varies, check yours with swapon --show)What you should see: rsync lists the files it transfers and ends with sent ... bytes received ... bytes and total size is .... Access errors show as rsync: ... Permission denied lines, so run it under sudo or root. The {...} syntax is bash brace expansion; in a plain sh shell, list the paths as separate --exclude options.
Plain tar and rsync do not encrypt anything. If the target is storage you do not control, encrypt the copy (below) or use a tool that does it for you.
You cannot copy the database files from under a running database engine: you get a torn snapshot. You need a dump, where the engine exports the data in a consistent form.
PostgreSQL, one database in its own compressed format:
sudo -u postgres pg_dump -Fc mydb > /root/db/mydb-$(date +%F).dump
MySQL or MariaDB, all databases (run as root, authentication goes over the socket):
mysqldump --single-transaction --quick --all-databases | gzip > /root/db/all-$(date +%F).sql.gz
-Fc on pg_dump is Postgres's own compressed format; it makes selective restore with pg_restore easy--single-transaction takes a consistent view of InnoDB tables without blocking writes; it does not work for old MyISAM tables, which need --lock-all-tables--quick streams row by row instead of building the whole table in memorypg_dump and pg_restore ship with the PostgreSQL server (version 16 on Ubuntu 24.04, 14 on 22.04); on MariaDB mysqldump is also available as mariadb-dump (/usr/bin/mariadb-dump)Simple rotation: the directory holds only dumps, so delete anything older than 7 days:
find /root/db -type f -mtime +7 -delete
From there restic picks up these dumps along with the rest of the files and carries them off the server already encrypted.
tar, rsync and pg_dump are building blocks. To turn them into a real backup system you have to handle encryption, deduplication (not storing the same thing ten times), incrementals (copying only the changes), rotation, and integrity checks yourself. restic and borg are finished systems with all of that inside:
restic is simpler to start and supports many targets: SFTP, S3-compatible storage, a local disk. borg is older, a little faster on large data and more space-efficient, but the target must be local or reachable over SSH with borg installed. For your first backup system, use restic; reach for borg when you have a dedicated backup server and very large data.
Install (borg too, in case you decide to use it):
apt install -y restic borgbackup
On Ubuntu 24.04 the repository gives you restic 0.16.4 and borg 1.2.8, which is enough for everything below. On older LTS the version is lower (restic around 0.12-0.14 on 22.04) and some flags, including --read-data-subset=5%, may be missing - then update it with restic self-update or take the binary from the GitHub release page.
Set up access to the repository, the place where restic stores copies. Here is an SFTP example to another machine (needs key-based SSH access to the target):
export RESTIC_REPOSITORY="sftp:backup@backuphost:/srv/restic/web01"
export RESTIC_PASSWORD="a-long-random-passphrase"
restic init
The repository password is the encryption key. Lose it and nobody, you included, can read the copy. Keep it separate from the server: a password manager, paper in a safe.
First backup, listing the directories:
restic backup /etc /root /home /var/www
The end of the output reads Files: N new, ..., Added to the repository: ..., snapshot a1b2c3d4 saved. That is the success signal.
List the points:
restic snapshots
Rotation: keep 7 daily, 4 weekly, 6 monthly, drop the rest and reclaim space:
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
Check that the repository is intact:
restic check
A manual backup gets forgotten. A systemd timer (the standard scheduler in Linux, like cron but with a log and a clear status) runs the copy for you.
Credentials file /root/.restic-env (root only: chmod 600 /root/.restic-env):
RESTIC_REPOSITORY=sftp:backup@backuphost:/srv/restic/web01
RESTIC_PASSWORD=a-long-random-passphrase
Service /etc/systemd/system/restic-backup.service:
[Unit]
Description=restic backup
[Service]
Type=oneshot
EnvironmentFile=/root/.restic-env
ExecStart=/usr/bin/restic backup /etc /root /home /var/www
ExecStartPost=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
ExecStartPost=/usr/bin/curl -fsS -m 10 https://hc-ping.com/YOUR-UUID
Type=oneshot: the service runs and exits, it is not a daemonEnvironmentFile pulls the RESTIC_* variables from the protected file so passwords are not in the unitExecStartPost rotates right after a successful backupExecStartPost pings a monitoring service (Healthchecks.io and similar). It ran, the ping went out. It failed, no ping, and the monitor alerts you. This is confirmed: if ExecStart exits non-zero, no ExecStartPost runs, so the ping is strictly a success signalTimer /etc/systemd/system/restic-backup.timer:
[Unit]
Description=daily restic backup
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
RandomizedDelaySec=15m
[Install]
WantedBy=timers.target
OnCalendar: when to run (every day at 03:30)Persistent=true: if the server was off at that time, run the missed backup at bootRandomizedDelaySec: a random start spread so you do not hit the storage in one exact secondEnable and check:
systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer
The last command shows a timer row with the columns NEXT, LEFT, LAST, PASSED, UNIT, ACTIVATES; the NEXT time is shifted by a random delta because of RandomizedDelaySec. To test right now: systemctl start restic-backup.service, then journalctl -u restic-backup.service -e.
Prefer cron? The line 30 3 * * * . /root/.restic-env && restic backup /etc /root /home /var/www in crontab -e does the same, without the log and without running missed jobs.
The 3-2-1 rule is the minimum sensible level:
Where to put the copies in practice: a second cheap VPS with a large disk and SSH access, object storage with an S3-compatible API, or a disk at home. The point is a different location: if you lose the whole server, the copy has to survive.
Set retention by how long a problem could go unnoticed. A typical set: 7 daily, 4-8 weekly, 6-12 monthly. A corrupted file that nobody opened for a month should still be in a copy.
Encryption is mandatory for anything stored off your server. restic and borg encrypt on their own. If you use tar or rsync to storage you do not control, encrypt before sending. In a script there is no one to type the passphrase, so read it from a file:
echo 'a-long-random-passphrase' > /root/.gpg-pass
chmod 600 /root/.gpg-pass
tar czf - /etc /home /var/www \
| gpg -c --batch --pinentry-mode loopback --passphrase-file /root/.gpg-pass \
-o /root/backup-$(date +%F).tar.gz.gpg
--batch --pinentry-mode loopback --passphrase-file are required in non-interactive mode. Without them gpg -c in a pipe cannot prompt for the passphrase and silently writes an empty file with exit code 0 - a silent backup failure you only notice when you try to restore/root/.gpg-pass at mode 600 and not in the same directory as the archiveTo decrypt later: gpg -d --batch --pinentry-mode loopback --passphrase-file /root/.gpg-pass /root/backup-2026-09-10.tar.gz.gpg | tar xzf -.
A backup you have never restored from is a guess, not a backup. Run a trial restore once a month.
restic, one directory into a temp folder:
restic restore latest --target /tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /tmp/restore-test/etc/nginx
Empty diff output means the copy matches the live files. Also check the integrity of the data in the repository:
restic check --read-data-subset=5%
Database dump: load it into a scratch database and check the data is there:
sudo -u postgres createdb restore_test
sudo -u postgres pg_restore -d restore_test /root/db/mydb-2026-09-10.dump
sudo -u postgres psql -d restore_test -c "select count(*) from users;"
sudo -u postgres dropdb restore_test
The row count roughly matches the live one, so the dump works.
Every few months, test a full restore too: take a clean server (see How to create a server in the HIP panel), restore the restic copy onto it, and check the site comes up. Until that is done, you do not know how long a restore takes or whether everything is in the copy.
/etc, the service will not start. Restore - the single file from restic. How - restic restore latest --include /etc/... --target /tmp/r, then copy the file back.pg_restore or mysql < dump.sql.restic restore of the path from the latest point.restic restore the data.rsync -aAX the directories, or restic restore onto the new server.No. The HIP panel has no snapshot feature: the one action that touches the disk is a reinstall (Rebuild), and it wipes everything. Backups of a HIP server are made only on your side, with tools on the server itself, writing out to somewhere else.
Install restic or borg, create a repository elsewhere (a second server over SFTP or object storage), and run restic backup on a schedule via a systemd timer. Separately, take database dumps with pg_dump or mysqldump. The copy is encrypted on the server before it leaves, so only encrypted data reaches the storage.
Both are incremental encrypted backup systems with deduplication and rotation. restic is simpler to start and supports many backends, including S3-compatible storage. borg is a little faster and more space-efficient on large data, but the target must be local or reachable over SSH with borg installed. For a first backup system, use restic.
Not on the same server. A second cheap VPS with a large disk and SSH access, object storage with an S3-compatible API, or a disk at home all work. The point is a different location: if you lose the whole server, the copy has to survive. Follow the 3-2-1 rule: three copies, two media, one off-site.
Create a systemd service that runs restic backup and restic forget --prune, and a timer with OnCalendar at your chosen time and Persistent=true. Add a ping to a monitoring service at the end: the backup ran, the ping went out; it failed, no ping, you get an alert. That way you learn about a broken backup before you need it.
Once a month, run a trial restore: restic restore one directory to a temp folder and diff against live, restic check --read-data-subset=5% for data integrity, and load a database dump into a scratch database to compare row counts. A backup you have never restored from does not count as working.