stuebinm
f654b33a56
this started with emily pointing out to me that it's possible to generate IP addresses for containers in Nix (hence no need to worry about ever having collisions, as we had before), but then I thought, hey, while I'm at it, I can also write a little container module so we have a little less repetition in our configs in general (and a more reasonable place for our custom evalConfig than just keeping it around in flake.nix). See the option descriptions in modules/containers.nix for further details. Apart from giving all containers a new IP address (and also shiny new IPv6 addresses), this should be a no-op for the actual built system.
95 lines
3.2 KiB
Nix
95 lines
3.2 KiB
Nix
{ 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.<name>.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/<name> at /persist into this container.";
|
|
};
|
|
|
|
bindSecrets = mkOption {
|
|
default = false;
|
|
type = types.bool;
|
|
description =
|
|
"Whether to mount /run/secrets/<name> 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));
|
|
}
|