{ config, lib, pkgs, ... }: let cfg = config.programs.schroot; iniFmt = pkgs.formats.ini { }; in { options = { programs.schroot = { enable = lib.mkEnableOption "schroot, a lightweight virtualisation tool"; package = lib.mkPackageOption pkgs "schroot" { }; settings = lib.mkOption { type = iniFmt.type; default = { }; example = { "noble" = { type = "directory"; description = "Ubuntu 24.04 Noble"; directory = "/srv/chroot/noble"; users = "my-user"; root-users = "my-user"; personality = "linux"; preserve-environment = false; profile = "my-profile"; shell = "/bin/bash"; }; }; description = '' Schroot configuration settings. For more details, see {manpage}`schroot.conf(5)`. ''; }; profiles = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule { options = { copyfiles = lib.mkOption { type = lib.types.listOf lib.types.str; example = [ "/etc/resolv.conf" ]; description = "A list of files to copy into the chroot from the host system."; }; fstab = lib.mkOption { type = lib.types.path; example = lib.literalExpression '' pkgs.writeText "my-schroot-fstab" ''' /proc /proc none rw,bind 0 0 /sys /sys none rw,bind 0 0 /dev /dev none rw,bind 0 0 /dev/pts /dev/pts none rw,bind 0 0 /home /home none rw,rbind 0 0 /tmp /tmp none rw,bind 0 0 /dev/shm /dev/shm none rw,bind 0 0 /nix /nix none ro,bind 0 0 /run/current-system /run/current-system none rw,bind 0 0 /run/wrappers /run/wrappers none rw,bind 0 0 ''' ''; description = '' A file in the format described in {manpage}`fstab(5)`, used to mount filesystems inside the chroot. The mount location is relative to the root of the chroot. ''; }; nssdatabases = lib.mkOption { type = lib.types.listOf lib.types.str; example = [ "passwd" "shadow" "group" "gshadow" "services" "protocols" "networks" "hosts" ]; description = '' System databases (as described in /etc/nsswitch.conf on GNU/Linux systems) to copy into the chroot from the host. ''; }; }; } ); default = { }; description = "Custom configuration profiles for schroot."; }; }; }; config = lib.mkIf cfg.enable { environment = { systemPackages = [ cfg.package ]; etc = { # schroot requires this directory to exist "schroot/chroot.d/.keep".text = ""; "schroot/schroot.conf".source = iniFmt.generate "schroot.conf" cfg.settings; } // (lib.attrsets.concatMapAttrs ( name: { copyfiles, fstab, nssdatabases, }: { "schroot/${name}/copyfiles".text = (lib.strings.concatStringsSep "\n" copyfiles) + "\n"; "schroot/${name}/fstab".source = fstab; "schroot/${name}/nssdatabases".text = (lib.strings.concatStringsSep "\n" nssdatabases) + "\n"; } ) cfg.profiles); }; security.wrappers.schroot = { source = "${cfg.package}/bin/schroot"; owner = "root"; group = "root"; setuid = true; }; # Schroot requires these directories to exist systemd.tmpfiles.rules = [ "d /var/lib/schroot/session - root root - -" "d /var/lib/schroot/unpack - root root - -" "d /var/lib/schroot/union - root root - -" "d /var/lib/schroot/union/overlay - root root - -" "d /var/lib/schroot/union/underlay - root root - -" ]; }; }