diff --git a/flake.nix b/flake.nix index cb9501a..7e3747c 100644 --- a/flake.nix +++ b/flake.nix @@ -38,33 +38,20 @@ system = "x86_64-linux"; config.allowUnfree = true; }; - evalConfig = config: (nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - config - { - nixpkgs.pkgs = pkgs.lib.mkForce pkgs; - imports = [ modules.nopersist profiles.container ]; - } - ]; - specialArgs = { - # some of our modules import each other, and evalConfig is used for containers - inherit modules evalConfig; - sources = inputs; - }; - }).config.system.build.toplevel; in { nixosConfigurations.parsons = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./parsons/configuration.nix ./modules/buildinfo.nix + ./modules/containers.nix sops-nix.nixosModules.sops { nixpkgs.pkgs = pkgs; } ]; specialArgs = { sources = inputs; - inherit modules evalConfig; + inherit modules profiles; + inherit (nixpkgs.lib) nixosSystem; }; }; diff --git a/modules/container-profile.nix b/modules/container-profile.nix index 53e051f..b50b6be 100644 --- a/modules/container-profile.nix +++ b/modules/container-profile.nix @@ -14,12 +14,5 @@ ''; }; - # I /suspect/ this is not actually needed. - # TODO: find spoons to deal with potential breakage, test removing this - networking.defaultGateway = { - address = "192.168.100.1"; - interface = "eth0"; - }; - system.stateVersion = lib.mkDefault "21.05"; } diff --git a/modules/containers.nix b/modules/containers.nix new file mode 100644 index 0000000..af46181 --- /dev/null +++ b/modules/containers.nix @@ -0,0 +1,95 @@ +{ 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)); +} diff --git a/parsons/forgejo.nix b/parsons/forgejo.nix index 2832b22..6d71ab2 100644 --- a/parsons/forgejo.nix +++ b/parsons/forgejo.nix @@ -1,19 +1,8 @@ -{ config, lib, pkgs, evalConfig, ... }: +{ config, lib, pkgs, ... }: { - containers.forgejo = { - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.10"; - autoStart = true; - ephemeral = true; - bindMounts = { - "/persist" = { - hostPath = "/persist/containers/forgejo"; - isReadOnly = false; - }; - }; - path = evalConfig ({ config, lib, pkgs, ... }: { + hacc.containers.forgejo = { + config = { lib, pkgs, ... }: { system.stateVersion = "21.11"; environment.systemPackages = [ pkgs.forgejo ]; @@ -79,7 +68,7 @@ services.openssh = { enable = true; listenAddresses = [ { - addr = "192.168.100.10"; + addr = config.containers.forgejo.localAddress; port = 22; } ]; settings = { @@ -87,7 +76,7 @@ AcceptEnv = "GIT_PROTOCOL"; }; }; - }); + }; }; services.nginx.virtualHosts."git.infra4future.de" = { diff --git a/parsons/hedgedoc-hacc.nix b/parsons/hedgedoc-hacc.nix index 35462f2..05575c6 100644 --- a/parsons/hedgedoc-hacc.nix +++ b/parsons/hedgedoc-hacc.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, evalConfig, ... }: +{ config, lib, pkgs, ... }: { @@ -6,20 +6,11 @@ "hedgedoc-hacc/env" = {}; }; - containers.pad-hacc = { - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.5"; - autoStart = true; - ephemeral = true; - bindMounts = { - "/persist" = { - hostPath = "/persist/containers/pad-hacc"; - isReadOnly = false; - }; - "/secrets".hostPath = "/run/secrets/hedgedoc-hacc"; - }; - path = evalConfig ({ config, lib, ... }: { + containers.pad-hacc.bindMounts = { + "/secrets".hostPath = "/run/secrets/hedgedoc-hacc"; + }; + hacc.containers.pad-hacc = { + config = { config, lib, ... }: { services.hedgedoc = { enable = true; settings = { @@ -78,7 +69,7 @@ location = "/persist/backups/postgres"; }; hacc.bindToPersist = [ "/var/lib/hedgedoc" ]; - }); + }; }; services.nginx.virtualHosts."pad.hacc.earth" = { enableACME = true; diff --git a/parsons/hedgedoc-i4f.nix b/parsons/hedgedoc-i4f.nix index 97ca2ce..aa210d9 100644 --- a/parsons/hedgedoc-i4f.nix +++ b/parsons/hedgedoc-i4f.nix @@ -1,19 +1,8 @@ -{ config, lib, pkgs, evalConfig, ... }: +{ config, lib, pkgs, ... }: { - containers.pad-i4f = { - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.6"; - autoStart = true; - ephemeral = true; - bindMounts = { - "/persist" = { - hostPath = "/persist/containers/pad-i4f"; - isReadOnly = false; - }; - }; - path = evalConfig ({ config, lib, ... }: { + hacc.containers.pad-i4f = { + config = { config, lib, ... }: { services.hedgedoc = { enable = true; settings = { @@ -57,7 +46,7 @@ location = "/persist/backups/postgres"; }; hacc.bindToPersist = [ "/var/lib/hedgedoc" ]; - }); + }; }; services.nginx.virtualHosts."pad.infra4future.de" = { diff --git a/parsons/mattermost.nix b/parsons/mattermost.nix index 890d16a..7c20c5c 100644 --- a/parsons/mattermost.nix +++ b/parsons/mattermost.nix @@ -1,26 +1,14 @@ -{ config, pkgs, lib, evalConfig, ...}: +{ config, pkgs, lib, ...}: { sops.secrets = { "mattermost/env" = {}; }; - containers.mattermost = { - autoStart = true; - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.3"; - ephemeral = true; + hacc.containers.mattermost = { + bindSecrets = true; - bindMounts = { - "/persist" = { - hostPath = "/persist/containers/mattermost"; - isReadOnly = false; - }; - "/secrets".hostPath = "/run/secrets/mattermost"; - }; - - path = evalConfig ({ config, lib, pkgs, ... }: { + config = { config, lib, pkgs, ... }: { systemd.services.mattermost.serviceConfig.EnvironmentFile = lib.mkForce "/secrets/env"; @@ -218,7 +206,7 @@ startAt = "*-*-* 23:45:00"; location = "/persist/backups/postgres"; }; - }); + }; }; services.nginx.virtualHosts."mattermost.infra4future.de" = { diff --git a/parsons/nextcloud.nix b/parsons/nextcloud.nix index 85bfcb6..401c002 100644 --- a/parsons/nextcloud.nix +++ b/parsons/nextcloud.nix @@ -1,19 +1,8 @@ -{ config, lib, pkgs, evalConfig, ... }: +{ config, lib, pkgs, ... }: { - containers.nextcloud = { - autoStart = true; - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.2"; - ephemeral = true; - bindMounts = { - "/persist" = { - hostPath = "/persist/containers/nextcloud"; - isReadOnly = false; - }; - }; - path = evalConfig ({ config, lib, pkgs, ... }: { + hacc.containers.nextcloud = { + config = { config, lib, pkgs, ... }: { environment.systemPackages = [ pkgs.htop ]; services.nextcloud = { @@ -82,7 +71,7 @@ requires = ["postgresql.service"]; after = ["postgresql.service"]; }; - }); + }; }; services.nginx.virtualHosts."cloud.infra4future.de" = { diff --git a/parsons/tracktrain.nix b/parsons/tracktrain.nix index c1ae335..f4df212 100644 --- a/parsons/tracktrain.nix +++ b/parsons/tracktrain.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, evalConfig, ... }: +{ config, lib, pkgs, ... }: let tracktrain-config = '' @@ -25,14 +25,14 @@ in enableACME = true; forceSSL = true; locations."/" = { - proxyPass = "http://192.168.42.41:4000"; + proxyPass = "http://${config.containers.tracktrain.localAddress}:4000"; proxyWebsockets = true; }; # note: this shadows the /metrics endpoint of tracktrain # in case you remove this, please consider putting something # else here to keep it from being publicly scrapable locations."/metrics/" = { - proxyPass = "http://192.168.42.41:2342"; + proxyPass = "http://${config.containers.tracktrain.localAddress}:2342"; proxyWebsockets = true; extraConfig = '' rewrite ^/metrics/(.*) /$1 break; @@ -40,21 +40,10 @@ in }; }; - containers.tracktrain = { - privateNetwork = true; - hostAddress = "192.168.42.40"; - localAddress = "192.168.42.41"; - autoStart = true; - ephemeral = true; - bindMounts = { - "/persist" = { - hostPath = "/persist/containers/tracktrain"; - isReadOnly = false; - }; - "/secrets".hostPath = "/run/secrets/tracktrain"; - }; + hacc.containers.tracktrain = { + bindSecrets = true; - path = evalConfig ({ config, lib, pkgs, ... }: { + config = { config, lib, pkgs, ... }: { system.stateVersion = "21.11"; users.users.tracktrain = { @@ -151,7 +140,7 @@ in systemd.services.grafana.serviceConfig.EnvironmentFile = "/secrets/env"; hacc.bindToPersist = [ "/var/lib/grafana" ]; - }); + }; }; } diff --git a/parsons/uffd.nix b/parsons/uffd.nix index b2d2048..747ed76 100644 --- a/parsons/uffd.nix +++ b/parsons/uffd.nix @@ -1,19 +1,8 @@ -{ config, lib, pkgs, evalConfig, ... }: +{ config, lib, pkgs, ... }: { - containers.uffd = { - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.9"; - autoStart = true; - ephemeral = true; - bindMounts = { - "/persist" = { - hostPath = "/persist/containers/uffd"; - isReadOnly = false; - }; - }; - path = evalConfig ({ config, lib, pkgs, ... }: { + hacc.containers.uffd = { + config = { config, lib, pkgs, ... }: { services.uwsgi = { enable = true; plugins = [ "python3" ]; @@ -29,7 +18,7 @@ hook-pre-app = "exec:FLASK_APP=${pkgs.uffd}/lib/python3.10/site-packages/uffd flask db upgrade"; }; }; - }); + }; }; services.nginx.virtualHosts."login.infra4future.de" = { enableACME = true;