Network backups (restic)
The darkone.service.restic module backs up fleet hosts with
restic 🡕: each host (client) pushes its data to a
repository, either local or remote via a zone REST server.
Principles
Section titled “Principles”Two roles, one module:
- REST server: a host that declares the
resticservice inconfig.yaml. It stores repositories for all hosts and listens on the internal network. - Client: any host with
enable = truethat declarestargets(backup destinations).
Repository layout, by category:
<root>/<host>/system # "system" category (/ minus exclusions)<root>/<host>/srv/nfs # "nfs" category (/srv/nfs/<...>)<root>/<host>/srv/medias # "media" category (/srv/medias/<...>)Setting up a backup server
Section titled “Setting up a backup server”-
In
etc/config.yaml, add theresticservice to the server host:services:restic: -
Attach the backup disk and mount it on
/mnt/backupin the host configuration (usr/machines/<host>/), with thenofailoption:fileSystems."/mnt/backup" = {device = "/dev/disk/by-uuid/<uuid>";fsType = "ext4";options = [ "nofail" ];};# The REST server only starts once the disk is mounted.systemd.services.restic-rest-server = {requires = [ "mnt-backup.mount" ];after = [ "mnt-backup.mount" ];}; -
The repository is stored under
serverDataDir(default/mnt/backup/restic). The firewall opens the REST port on the internal interface automatically.
Adding a client
Section titled “Adding a client”Declare one or more targets in the host configuration:
darkone.service.restic = { enable = true; targets = [ { # Remote repository via the zone's REST server. root = "rest:http://restic.home.example.net:8888"; zone = "home"; categories = [ "system" "nfs" ]; } ];};target fields:
| Field | Role |
|---|---|
name | Identifier (default main), suffix for jobs/units. |
root | Local path or rest:// URL. |
zone | Zone that selects the restic-password-<zone> passphrase. |
categories | Data to back up: system, nfs, medias. |
Generating passwords
Section titled “Generating passwords”An idempotent recipe creates missing secrets (never overwrites):
just passwd-resticIt generates, in usr/secrets/secrets.yaml:
- one
restic-password-<zone>passphrase per zone; - one
restic/<host>/rest-passwordcredential per fleet host.
Running a manual backup
Section titled “Running a manual backup”The module creates one systemd service per target × category pair, named
restic-backups-<category>-<name> (the <name> comes from the target’s name
field, main by default). Examples: restic-backups-system-main,
restic-backups-nfs-main.
-
List the backup services present on the host:
Fenêtre de terminal systemctl list-units 'restic-backups-*' -
Trigger an immediate backup without waiting for the timer:
Fenêtre de terminal sudo systemctl start restic-backups-system-main.service -
Follow its progress in real time:
Fenêtre de terminal journalctl -fu restic-backups-system-main.service
Repository isolation
Section titled “Repository isolation”The REST server runs with private repositories (privateRepos = true): each host
only accesses the repository whose path starts with its own hostname. The
module automatically aligns the REST account (<hôte>) with the repository prefix
(<racine>/<hôte>/...), so isolation is permanent → no configuration needed.
An attempt to access another host’s repository returns a 403 error.
Restoring
Section titled “Restoring”On the target host, secrets are already in place. List then restore:
# Adjust the repository zone (and category: system, srv/nfs, srv/medias).ZONE=home
# REST access variables (generated by sops) and repository passphrase.set -a; . /run/secrets/rendered/restic-rest-env; set +aexport RESTIC_PASSWORD_FILE=/run/secrets/restic-password-$ZONEexport RESTIC_REPOSITORY=rest:http://restic.$ZONE.example.net:8888/$(hostname)/system
restic snapshotsrestic restore latest --target /restoreVerifying
Section titled “Verifying”-
On a server, one account per fleet host in the htpasswd file:
Fenêtre de terminal sudo cut -d: -f1 /run/restic-rest/htpasswd -
On a client, run a manual backup (see above) and check that it completes without errors.
-
Isolation: from a client, accessing another host’s repository must be denied (401/403 error).