Skip to content

Services Backup Reference

The services.backup module provides a declarative and reusable way to configure live backups for stateful applications (such as Jellyfin) on NixOS, safely handling SQLite databases and other files.

How it Works

When a backup job is defined, the module dynamically creates:

  1. A systemd service (backup-<name>.service):
  2. Triggers an online hot-backup (.backup) of configured SQLite database files.
  3. Performs an rsync of all other files to the destination directory (excluding the active database files and their WAL/SHM sidecars to prevent corruption).
  4. A systemd timer (backup-<name>.timer): Schedules the job to run daily (by default) or on a custom schedule.
  5. Automatic ZFS Mounts: If zfs.enable is true and a zfs.pool is defined, the module automatically generates a legacy NixOS fileSystems mount configuration for any job directory starting with /${pool}/.

Setting up a New Job (e.g. Jellyfin)

1. Create and configure the ZFS dataset

Configure the service backup datasets as legacy mounts so that mounting is managed by NixOS/systemd.

# Create the dataset
sudo zfs create -p bardioc/services/jellyfin

# Set its mountpoint property to legacy
sudo zfs set mountpoint=legacy bardioc/services/jellyfin

2. Configure NixOS

Add the backup job to your host configuration (e.g. titan.nix). Specify the baseDir and ZFS pool at the host level:

services.backup = {
  enable = true;
  baseDir = "/bardioc/services";
  zfs = {
    enable = !vmTest;
    pool = "bardioc";
  };
  jobs.jellyfin = {
    srcDir = "/var/lib/jellyfin";
    sqliteDbs = [
      "data/jellyfin.db"
    ];
  };
};

Testing & Troubleshooting

Trigger a manual backup

You can force a backup to run at any time using:

sudo systemctl start backup-jellyfin.service

Check service logs

journalctl -u backup-jellyfin.service

Verify backups

Ensure the directory structure and files were copied correctly:

ls -la /bardioc/services/jellyfin/db
ls -la /bardioc/services/jellyfin/files