{ config, lib, pkgs, modules, profiles, sources, nixosSystem, ... }: let mkIPv4 = index: local: "192.168.${if local then "100" else "101"}.${toString index}"; mkIPv6 = index: local: "fd00::${if local then "100" else "101"}:${toString index}"; evalConfig = nixosConfig: (nixosSystem { inherit (config.nixpkgs) system; modules = [ nixosConfig modules.nopersist profiles.container { nixpkgs.pkgs = lib.mkForce pkgs; } ]; specialArgs = { inherit modules sources; }; }).config.system.build.toplevel; in { options.hacc.containers = with lib.options; mkOption { description = '' hacc-specific containers. These are a thin wrapper around "normal" nixos containers: - they automatically get an IPv4/IPv6 address assigned (note that these are not guaranteed to be stable across config changes, so please use {option}`containers..hostAddress` & friends to reference them elsewhere) - they set a couple default options (e.g. ephemeral, autoStart, privateNetwork) - they are evaluated with our own version of {nix}`evalConfig`, which includes a couple more modules by default, use our version of `nixpkgs`, and includes the {nix}`profiles.containers` profile setting sane defaults for containers. ''; default = { }; type = with lib.types; types.attrsOf (types.submodule { options = { bindToPersist = mkOption { default = true; type = types.bool; description = "Wether to mount /persist/containers/ at /persist into this container."; }; bindSecrets = mkOption { default = false; type = types.bool; description = "Whether to mount /run/secrets/ at /secrets into this container."; }; config = mkOption { type = types.unspecified; description = "The container's config, to be evaluated with our own {nix}`evalConfig`."; }; }; }); }; # wrapped into imap1, which enumerates the containers; IP addresses are then # simply assigned based on the order the containers are in the list. config.containers = lib.mkMerge (lib.imap1 (index: { name, value }: let container = value; in { ${name} = { hostAddress = mkIPv4 index false; localAddress = mkIPv4 index true; hostAddress6 = mkIPv6 index false; localAddress6 = mkIPv6 index true; privateNetwork = true; autoStart = true; ephemeral = true; bindMounts = lib.mkMerge [ (lib.mkIf container.bindToPersist { "/persist" = { hostPath = "/persist/containers/${name}"; isReadOnly = false; }; }) (lib.mkIf container.bindSecrets { "/secrets" = { hostPath = "/run/secrets/${name}"; isReadOnly = true; }; }) ]; path = evalConfig container.config; }; }) (lib.attrsToList config.hacc.containers)); }