Chapters

Disko

Disko describes the disk layout in Nix, including partitions, ZFS pools, datasets and mountpoints. Copland uses this layout to prepare the disk during installation, and Disko generates the corresponding fileSystems entries for the installed system. Datasets defined here are not declared again under zfs.datasets.

Service datasets

Services can declare their own persistent storage through zfs.datasets. Copland creates missing datasets during activation below an existing pool, so adding storage for a service does not require running the disk installation again. Each declaration specifies a mountpoint and can set ownership and a quota, while the stored data remains independent of the system generation.

Declaration

This module gives foo its own dataset at /var/lib/foo with a quota of 10 GiB. Replace tank with an existing pool on your machine.

{ ... }:
{
  users.groups.foo = { };
  users.users.foo = {
    isSystemUser = true;
    group = "foo";
    home = "/var/lib/foo";
  };

  zfs.datasets."tank/foo" = {
    mountpoint = "/var/lib/foo";
    owner = "foo";
    group = "foo";
    quota = "10G";
  };
}

tank/foo names the ZFS dataset, while mountpoint determines where its contents are accessible. The foo account owns the mounted directory, allowing a service running as that user to store its data there. Configure the service itself to use /var/lib/foo as its data directory.

mountpoint is required. owner and group default to root, and quota defaults to null, which leaves the dataset's quota unchanged if it already exists. Ownership applies to the dataset's root directory, not recursively to every file inside it.

Activation

During activation, Copland imports the existing pool if necessary, creates missing datasets and mounts them at their declared paths. It applies any configured quota, checks that the expected ZFS dataset is actually mounted there, and sets the directory's owner and group.

Existing datasets and their contents are kept. If an existing dataset has a different mountpoint from the declaration, activation fails instead of moving it automatically. Removing a declaration does not delete the dataset or its data.