- Nix 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| AGENTS.md | ||
| COPYING | ||
| flake.lock | ||
| flake.nix | ||
| module.nix | ||
| README.md | ||
snapper-homedirs
A NixOS module that places selected users' home directories in individual Btrfs
subvolumes and configures Snapper timeline snapshots for them. On first
activation it creates the per-user subvolumes, migrates an existing non-mounted
home directory, and bind-mounts the new home subvolume at /home/<user>.
Requirements and safety
services.btrfsHomeSnapshots.basemust reside on Btrfs. The module creates Btrfs subvolumes beneath it.- Configure only normal users and make a backup before first activation. The one-time migration moves existing home contents and removes the now-empty source directories.
- Do not reuse a base containing data that conflicts with the module's layout:
<base>/<user>,<base>/<user>/home, and<base>/<user>/.snapshots. - The module enables Snapper timeline creation and cleanup for every configured user. Snapshot retention consumes the space of the underlying Btrfs filesystem; retention is not a substitute for off-machine backups.
Flake consumption
Add this flake as an input and import its default NixOS module:
{
inputs.snapper-homedirs.url = "<flake source>";
outputs = { nixpkgs, snapper-homedirs, ... }: {
nixosConfigurations.host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ snapper-homedirs.nixosModules.default ./configuration.nix ];
};
};
}
Configuration
The smallest configuration uses the defaults: /var/users as the Btrfs-backed
base, snapshots every five minutes at minute seven, and retention of 24 hourly,
6 monthly, and 0 yearly snapshots.
{
services.btrfsHomeSnapshots = {
enable = true;
users = [ "alice" "bob" ];
};
}
Set the Btrfs base, systemd calendar expression, and all retention limits when you need a different policy:
{
services.btrfsHomeSnapshots = {
enable = true;
base = "/home-pool";
users = [ "alice" "bob" ];
snapshotInterval = "hourly";
limits = {
hourly = 48;
monthly = 12;
yearly = 2;
};
};
}
Each user receives a Snapper configuration named home-<user>. Its snapshot
subvolume is <base>/<user>/.snapshots; the bind-mounted home is
<base>/<user>/home.
License
Copyright 2026 Alexander Khodyrev. Licensed under the GNU Affero General Public
License, version 3 or later (AGPL-3.0-or-later). See COPYING.