How YunoHost Backups Actually Work: Per-App Scripts, Archives, and the Mistakes That Break Restores
YunoHost backups work because each app ships its own backup and restore scripts. Here's the mechanism, a worked WordPress example, and the mistakes that break restores.
05 Sept 2025, 14:56 UTC

YunoHost's backup system works because every packaged app ships its own backup and restore scripts. When you run yunohost backup create, the core doesn't guess which files matter — it executes each app's declared backup logic, bundles the results with system configuration into a single archive, and drops it in /home/yunohost.backup/archives/. That design is why restores usually work cleanly, and also why the two most common failures — keeping archives on the same disk, and never test-restoring — are entirely avoidable.
The mechanism: declarative per-app scripts plus system hooks
A YunoHost app package contains a scripts/backup file. That script declares what the app needs preserved: its installation directory, its data directory, its database (via helpers that dump MySQL/PostgreSQL), and its configuration. You don't maintain an rsync include list per app; the app maintainer already did.
The system side is handled by backup hooks in /usr/share/yunohost/hooks/backup/, which capture core configuration, the LDAP directory (users and permissions), and SSO settings. When you create a backup, YunoHost runs the system hooks plus the backup script of each selected app and assembles everything into one .tar archive (compression defaults vary by release) named by timestamp, for example 20261013-015844.tar.
Each archive contains an info.json manifest listing the apps it holds and their versions. That manifest is what makes archives self-describing: restore can validate what it's about to apply, and you can inspect an archive before trusting it.
A worked example: backing up and restoring WordPress
Run these on the YunoHost server as root (or via sudo). To back up only the WordPress app:
yunohost backup create --apps wordpressExpected result: a new archive appears under /home/yunohost.backup/archives/, and yunohost backup list shows the new timestamped entry. Before relying on it, inspect the manifest:
tar -xOf /home/yunohost.backup/archives/20261013-015844.tar info.jsonConfirm the manifest lists wordpress and the version you expect. (The exact member path inside the tar can vary; if info.json isn't found at the top level, list the archive with tar -tf first.)
To restore later — on the same machine after a breakage, or on a fresh YunoHost install:
yunohost backup restore 20261013-015844 --apps wordpressThis runs the app's packaged scripts/restore, which recreates the system user, restores the database, rebuilds permissions, and re-registers the app with the SSO. You are not manually untarring files into place.
Two cautions on flags: exact command options differ across YunoHost releases (4.x vs 11/12.x), so check yunohost backup create --help on your system. And restoring on a fresh machine generally requires copying the archive into /home/yunohost.backup/archives/ first so the restore command can find it by name.
Getting archives off the box
Backups in /home/yunohost.backup/archives/ sit on the same disk as the services they protect. A disk failure or a botched upgrade destroys both. This is the single most common way YunoHost \"backups\" turn out to be worthless.
The minimal fix is copying archives elsewhere after creation, for example from another machine:
rsync -a root@your-server:/home/yunohost.backup/archives/ /mnt/backup/yunohost/For something more robust, the community-maintained Borg and BorgBase apps integrate deduplicated, encrypted, remote backups with YunoHost's archive model. Whichever route you pick, automate it — a manual copy step is a step that eventually gets skipped.
Limits and common mistakes
- Disk space. Creating an archive needs roughly as much free space as the data being backed up. Apps with large data directories (file sync, media) can fill the disk mid-backup. Check
df -hbefore backing up big apps. - Version drift. Restore runs the app's packaged restore script, so the app must still be installable and compatible with your current YunoHost version. Restoring a very old archive onto a much newer system can fail when dependencies or script helpers have changed. Keep archives reasonably current, and note the YunoHost version alongside them.
- Never testing restores. A backup that has never been restored is a hypothesis. The practical check is restoring onto a spare machine or VM: install the same YunoHost major version, copy the archive into
/home/yunohost.backup/archives/, runyunohost backup restore <name>, and verify the app actually serves content and logins work. - Assuming one archive covers everything. If you create backups with
--appsfilters, confirm withyunohost backup listand the manifest that every app you care about is included somewhere. A backup of \"everything except the big app\" is easy to create by accident.
A verification routine worth keeping
- Create the backup and confirm it exists:
yunohost backup listand a file in/home/yunohost.backup/archives/. - Inspect
info.jsonto confirm expected apps and versions. - Replicate the archive off the server (rsync, Borg, or similar).
- Periodically — at least after major upgrades — restore to a VM and exercise the app.
The per-app script model does the hard part for you: consistent, complete captures without hand-maintained file lists. What's left on you is the unglamorous part — off-box copies and test restores — and that's exactly where most real-world YunoHost backup failures live.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.