From dca90a59f68215fdb8368b255ba18e9526add0be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Wed, 12 Oct 2022 19:58:09 +0100 Subject: [PATCH] webserver: Use a hardened systemd unit instead of a container --- configuration/default.nix | 22 +- configuration/ids.nix | 11 - configuration/services/webserver.nix | 59 ++-- flake.lock | 395 ++++++++++++++++++++------- flake.nix | 13 +- modules/virtualisation/pods.nix | 222 --------------- 6 files changed, 321 insertions(+), 401 deletions(-) delete mode 100644 configuration/ids.nix delete mode 100644 modules/virtualisation/pods.nix diff --git a/configuration/default.nix b/configuration/default.nix index 69c129b..a30220f 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,5 +1,4 @@ { - config, pkgs, lib, ... @@ -10,7 +9,6 @@ ./services/webserver.nix ./services/starbound.nix ./services/postgres.nix - ./ids.nix ./sops.nix ]; @@ -66,30 +64,12 @@ recommendedProxySettings = true; clientMaxBodySize = "10G"; domain = "tlater.net"; - - virtualHosts = let - proxyPassToPort = port: extra: - lib.recursiveUpdate { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://127.0.0.1:${toString port}"; - extraConfig = '' - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - ''; - } - extra; - domain = config.services.nginx.domain; - in { - "${domain}" = proxyPassToPort 3002 {serverAliases = ["www.${domain}"];}; - }; }; security.acme = { - email = "tm@tlater.net"; + defaults.email = "tm@tlater.net"; acceptTerms = true; }; - virtualisation.oci-containers.backend = "podman"; - system.stateVersion = "20.09"; } diff --git a/configuration/ids.nix b/configuration/ids.nix deleted file mode 100644 index 352b4d3..0000000 --- a/configuration/ids.nix +++ /dev/null @@ -1,11 +0,0 @@ -{...}: { - ids.uids = { - # System user ids start at 400 (see nixos/modules/programs/shadow.nix) - webserver = 400; - # The limit is 999 - }; - - ids.gids = { - webserver = 400; - }; -} diff --git a/configuration/services/webserver.nix b/configuration/services/webserver.nix index 093da3d..4a8bee4 100644 --- a/configuration/services/webserver.nix +++ b/configuration/services/webserver.nix @@ -1,47 +1,26 @@ -{ - config, - pkgs, - ... -}: { - users = { - extraUsers.webserver = { - uid = config.ids.uids.webserver; - group = config.users.extraGroups.webserver.name; - isSystemUser = true; - description = "tlater.net web server user"; +{config, ...}: let + domain = config.services.nginx.domain; +in { + services.tlaternet-webserver = { + enable = true; + listen = { + addr = "127.0.0.1"; + port = 8000; }; - extraGroups.webserver = {gid = config.ids.gids.webserver;}; }; - virtualisation.oci-containers.containers.webserver = { - image = "tlaternet/webserver"; + # Set up SSL + services.nginx.virtualHosts."${domain}" = let + inherit (config.services.tlaternet-webserver.listen) addr port; + in { + serverAliases = ["www.${domain}"]; - imageFile = pkgs.dockerTools.buildImage { - name = "tlaternet/webserver"; - tag = "latest"; - contents = pkgs.tlaternet-webserver.webserver; + forceSSL = true; + enableACME = true; + extraConfig = '' + add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; + ''; - config = let - uid = toString config.users.extraUsers.webserver.uid; - gid = toString config.users.extraGroups.webserver.gid; - in { - Cmd = ["tlaternet-webserver"]; - Volumes = {"/srv/mail" = {};}; - Env = [ - "ROCKET_PORT=3002" - "ROCKET_TEMPLATE_DIR=${pkgs.tlaternet-templates.templates}/browser/" - ]; - ExposedPorts = {"3002" = {};}; - User = "${uid}:${gid}"; - }; - }; - - ports = ["3002:3002"]; - volumes = ["tlaternet-mail:/srv/mail"]; - extraOptions = [ - "--hostname=tlater.net" - # Rocket 0.4 doesn't support SIGTERM anyway, so SIGKILL is the cleanest exit possible. - "--stop-signal=SIGKILL" - ]; + locations."/".proxyPass = "http://${addr}:${toString port}"; }; } diff --git a/flake.lock b/flake.lock index c6f9923..11b5c2c 100644 --- a/flake.lock +++ b/flake.lock @@ -1,63 +1,202 @@ { "nodes": { - "flake-utils": { - "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "naersk": { + "alejandra": { "inputs": { + "fenix": "fenix", + "flakeCompat": "flakeCompat", "nixpkgs": [ "tlaternet-webserver", + "dream2nix", "nixpkgs" ] }, "locked": { - "lastModified": 1632266297, - "narHash": "sha256-J1yeJk6Gud9ef2pEf6aKQemrfg1pVngYDSh+SAY94xk=", - "owner": "nmattia", - "repo": "naersk", - "rev": "ee7edec50b49ab6d69b06d62f1de554efccb1ccd", + "lastModified": 1658427149, + "narHash": "sha256-ToD/1z/q5VHsLMrS2h96vjJoLho59eNRtknOUd19ey8=", + "owner": "kamadorueda", + "repo": "alejandra", + "rev": "f5a22afd2adfb249b4e68e0b33aa1f0fb73fb1be", "type": "github" }, "original": { - "owner": "nmattia", - "repo": "naersk", + "owner": "kamadorueda", + "repo": "alejandra", "type": "github" } }, + "crane": { + "flake": false, + "locked": { + "lastModified": 1661875961, + "narHash": "sha256-f1h/2c6Teeu1ofAHWzrS8TwBPcnN+EEu+z1sRVmMQTk=", + "owner": "ipetkov", + "repo": "crane", + "rev": "d9f394e4e20e97c2a60c3ad82c2b6ef99be19e24", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "devshell": { + "flake": false, + "locked": { + "lastModified": 1653917170, + "narHash": "sha256-FyxOnEE/V4PNEcMU62ikY4FfYPo349MOhMM97HS0XEo=", + "owner": "numtide", + "repo": "devshell", + "rev": "fc7a3e3adde9bbcab68af6d1e3c6eb738e296a92", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "dream2nix": { + "inputs": { + "alejandra": "alejandra", + "crane": "crane", + "devshell": "devshell", + "flake-utils-pre-commit": "flake-utils-pre-commit", + "gomod2nix": "gomod2nix", + "mach-nix": "mach-nix", + "nixpkgs": "nixpkgs_2", + "poetry2nix": "poetry2nix", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1663323895, + "narHash": "sha256-ZmI9C8HNVz2w3OnB79WR/LIgVEY8tDnR8tEPi3hMiJk=", + "owner": "nix-community", + "repo": "dream2nix", + "rev": "25be741ec92c77b8308ca6a7ab89593fe37b6542", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "dream2nix", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "tlaternet-webserver", + "dream2nix", + "alejandra", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1657607339, + "narHash": "sha256-HaqoAwlbVVZH2n4P3jN2FFPMpVuhxDy1poNOR7kzODc=", + "owner": "nix-community", + "repo": "fenix", + "rev": "b814c83d9e6aa5a28d0cf356ecfdafb2505ad37d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "fenix_2": { + "inputs": { + "nixpkgs": [ + "tlaternet-webserver", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src_2" + }, + "locked": { + "lastModified": 1663396212, + "narHash": "sha256-dlK10QPTDYNpJ/vl2QPKOTrqEbQwAR/v2f4+xsetTkw=", + "owner": "nix-community", + "repo": "fenix", + "rev": "263cd7f991c07a9592a6e825bfc37b23b00eb244", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-utils-pre-commit": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakeCompat": { + "flake": false, + "locked": { + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "gomod2nix": { + "flake": false, + "locked": { + "lastModified": 1627572165, + "narHash": "sha256-MFpwnkvQpauj799b4QTBJQFEddbD02+Ln5k92QyHOSk=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "67f22dd738d092c6ba88e420350ada0ed4992ae8", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "gomod2nix", + "type": "github" + } + }, + "mach-nix": { + "flake": false, + "locked": { + "lastModified": 1634711045, + "narHash": "sha256-m5A2Ty88NChLyFhXucECj6+AuiMZPHXNbw+9Kcs7F6Y=", + "owner": "DavHau", + "repo": "mach-nix", + "rev": "4433f74a97b94b596fa6cd9b9c0402104aceef5d", + "type": "github" + }, + "original": { + "id": "mach-nix", + "type": "indirect" + } + }, "nixos-hardware": { "locked": { - "lastModified": 1650522846, - "narHash": "sha256-SxWHXRI3qJwswyXAtzsi6PKVY3KLNNnb072KaJthII8=", + "lastModified": 1665321371, + "narHash": "sha256-0SO6MTW0bX6lxZmz1AZW/Xmk+hnTd7/hp1vF7Tp7jg0=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "6b4ebea9093c997c5f275c820e679108de4871ab", + "rev": "236ba4df714131059945d7754c0aa3fbe9d2f74c", "type": "github" }, "original": { @@ -69,51 +208,134 @@ }, "nixpkgs": { "locked": { - "lastModified": 1650501692, - "narHash": "sha256-ApKf0/dc0SyB7zZ6yiiOQgcXAhCXxbSDyihHfRDIzx0=", + "lastModified": 1665466769, + "narHash": "sha256-L+qcHpb4Ac3PipMXJY/Ktbu1+KXy23WCZ8pXWmsf7zY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9887f024766aa27704d1f89f623efd1d063da92a", + "rev": "0b20bf89e0035b6d62ad58f9db8fdbc99c2b01e8", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-21.11", + "ref": "nixos-22.05", "repo": "nixpkgs", "type": "github" } }, + "nixpkgs-22_05": { + "locked": { + "lastModified": 1665279158, + "narHash": "sha256-TpbWNzoJ5RaZ302dzvjY2o//WxtOJuYT3CnDj5N69Hs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b3783bcfb8ec54e0de26feccfc6cc36b8e202ed5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-22.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1657638268, + "narHash": "sha256-blBNtQSslAFkg0Gym9fWNJk+bPxGSZib4SOcPrmTPi4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d80993b5f885515254746ba6d1917276ee386149", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "poetry2nix": { + "flake": false, + "locked": { + "lastModified": 1632969109, + "narHash": "sha256-jPDclkkiAy5m2gGLBlKgH+lQtbF7tL4XxBrbSzw+Ioc=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "aee8f04296c39d88155e05d25cfc59dfdd41cc77", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "1.21.0", + "repo": "poetry2nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-utils": [ + "tlaternet-webserver", + "dream2nix", + "flake-utils-pre-commit" + ], + "nixpkgs": [ + "tlaternet-webserver", + "dream2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646153636, + "narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", "sops-nix": "sops-nix", - "tlaternet-templates": "tlaternet-templates", "tlaternet-webserver": "tlaternet-webserver" } }, - "rust-overlay": { - "inputs": { - "flake-utils": [ - "tlaternet-webserver", - "flake-utils" - ], - "nixpkgs": [ - "tlaternet-webserver", - "nixpkgs" - ] - }, + "rust-analyzer-src": { + "flake": false, "locked": { - "lastModified": 1633400100, - "narHash": "sha256-kHQV7jZ2vVHVI9sfda1mUROVBbQbdfKcbIpKG9WdqGo=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "9c2fc6a62ccbc6f420d71ecac6bf0b84dbbee64f", + "lastModified": 1657557289, + "narHash": "sha256-PRW+nUwuqNTRAEa83SfX+7g+g8nQ+2MMbasQ9nt6+UM=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "caf23f29144b371035b864a1017dbc32573ad56d", "type": "github" }, "original": { - "owner": "oxalica", - "repo": "rust-overlay", + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_2": { + "flake": false, + "locked": { + "lastModified": 1662896065, + "narHash": "sha256-1LkSsXzI1JTAmP/GMTz4fTJd8y/tw8R79l96q+h7mu8=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "2e9f1204ca01c3e20898d4a67c8b84899d394a88", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", "type": "github" } }, @@ -121,14 +343,15 @@ "inputs": { "nixpkgs": [ "nixpkgs" - ] + ], + "nixpkgs-22_05": "nixpkgs-22_05" }, "locked": { - "lastModified": 1649756291, - "narHash": "sha256-KTll8bCINAzIUGaaMrbn9wb5nfhkXRLgmFrWGR/Dku0=", + "lastModified": 1665289655, + "narHash": "sha256-j1Q9mNBhbzeJykhObiXwEGres9qvP4vH7gxdJ+ihkLI=", "owner": "Mic92", "repo": "sops-nix", - "rev": "c2614c4fe61943b3d280ac1892fcebe6e8eaf8c8", + "rev": "0ce0449e6404c4ff9d1b7bd657794ae5ca54deb3", "type": "github" }, "original": { @@ -137,42 +360,20 @@ "type": "github" } }, - "tlaternet-templates": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1633432574, - "narHash": "sha256-IjGaJAQuFIJ1Is9gtHXsryPOnTDE6tlA61PUKuS8dzw=", - "ref": "master", - "rev": "555a2949bdf643c74b535bd0c623d98f99d33628", - "revCount": 61, - "type": "git", - "url": "https://gitea.tlater.net/tlaternet/tlaternet-templates.git" - }, - "original": { - "type": "git", - "url": "https://gitea.tlater.net/tlaternet/tlaternet-templates.git" - } - }, "tlaternet-webserver": { "inputs": { - "flake-utils": "flake-utils_2", - "naersk": "naersk", + "dream2nix": "dream2nix", + "fenix": "fenix_2", "nixpkgs": [ "nixpkgs" - ], - "rust-overlay": "rust-overlay" + ] }, "locked": { - "lastModified": 1633433130, - "narHash": "sha256-jkW+HV8cJvE86gppOEXQl2ke+bDHJ7SAp8eJp8pJ0N8=", + "lastModified": 1665402451, + "narHash": "sha256-zWaEzUJh0WFVoaLQsMoIj2D+QFhUBJw+f+XzoYqw3es=", "ref": "master", - "rev": "1232950c06ae16bf17fb16ac1f5f2231e971936b", - "revCount": 16, + "rev": "6c29bc5db001e75f5ca06fec726369b87d007a03", + "revCount": 47, "type": "git", "url": "https://gitea.tlater.net/tlaternet/tlaternet.git" }, diff --git a/flake.nix b/flake.nix index 5ff0a51..5603e08 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "tlater.net host configuration"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-21.11"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; nixos-hardware.url = "github:nixos/nixos-hardware/master"; sops-nix = { url = "github:Mic92/sops-nix"; @@ -13,10 +13,6 @@ url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git"; inputs.nixpkgs.follows = "nixpkgs"; }; - tlaternet-templates = { - url = "git+https://gitea.tlater.net/tlaternet/tlaternet-templates.git"; - inputs.nixpkgs.follows = "nixpkgs"; - }; }; outputs = { @@ -25,16 +21,11 @@ nixos-hardware, sops-nix, tlaternet-webserver, - tlaternet-templates, }: let system = "x86_64-linux"; overlays = [ (final: prev: { - tlaternet-webserver = - tlaternet-webserver.legacyPackages.${prev.system}.packages; - tlaternet-templates = - tlaternet-templates.legacyPackages.${prev.system}.packages; local = import ./pkgs { pkgs = prev; }; @@ -59,6 +50,7 @@ (import ./configuration/linode.nix) (import ./configuration/hardware-configuration.nix) sops-nix.nixosModules.sops + tlaternet-webserver.nixosModules.default ]; }; @@ -74,6 +66,7 @@ (import ./configuration) sops-nix.nixosModules.sops + tlaternet-webserver.nixosModules.default ({lib, ...}: { users.users.tlater.password = "insecure"; diff --git a/modules/virtualisation/pods.nix b/modules/virtualisation/pods.nix deleted file mode 100644 index 5a96cc8..0000000 --- a/modules/virtualisation/pods.nix +++ /dev/null @@ -1,222 +0,0 @@ -{ - lib, - config, - options, - ... -}: -with lib; let - cfg = config.virtualisation.pods; - list-to-args = arg: list: - concatStringsSep " " (map (e: "--${arg}=${escapeShellArg e}") list); - possibly-unset-arg = arg: val: (optionalString (val != null) "--${arg}=${escapeShellArg val}"); - - mkPod = name: pod: rec { - path = [config.virtualisation.podman.package]; - - wants = ["network.target"]; - after = ["network-online.target"]; - wantedBy = ["multi-user.target" "default.target"]; - - environment.PODMAN_SYSTEMD_UNIT = "%n"; - - preStart = concatStringsSep " " [ - "mkdir -p /run/podman/pods/ ;" - "podman pod create" - "--infra-conmon-pidfile=${escapeShellArg "/run/podman/pods/${name}.pid"}" - "--name=${escapeShellArg name}" - "--replace" - (list-to-args "add-host" pod.added-hosts) - (possibly-unset-arg "cgroup-parent" pod.cgroup-parent) - (list-to-args "dns" pod.dns) - (list-to-args "dns-opt" pod.dns-opt) - (list-to-args "dns-search" pod.dns-search) - (possibly-unset-arg "hostname" pod.hostname) - (possibly-unset-arg "infra" pod.infra) - (possibly-unset-arg "infra-command" pod.infra-command) - (possibly-unset-arg "infra-image" pod.infra-image) - (possibly-unset-arg "ip" pod.ip) - (possibly-unset-arg "mac-address" pod.mac-address) - (possibly-unset-arg "network" pod.network) - (possibly-unset-arg "network-alias" pod.network-alias) - (possibly-unset-arg "no-hosts" pod.no-hosts) - (list-to-args "publish" pod.publish) - (list-to-args "share" pod.share) - ]; - - script = "podman pod start ${escapeShellArg name}"; - preStop = "podman pod stop ${escapeShellArg name}"; - # `podman generate systemd` generates a second stop after the - # first; not sure why but clearly it's recommended. - postStop = preStop; - - serviceConfig = rec { - Type = "forking"; - TimeoutStopSec = 70; - Restart = "on-failure"; - PIDFile = "/run/podman/pods/${name}.pid"; - }; - }; -in { - options.virtualisation.pods = mkOption { - type = with types; - attrsOf (submodule { - options = { - added-hosts = mkOption { - type = listOf str; - default = []; - description = "Additional hosts to add to /etc/hosts for each container."; - example = literalExample '' - [ "database:10.0.0.1" ] - ''; - }; - - cgroup-parent = mkOption { - type = nullOr str; - default = null; - description = "The cgroups path under which the pod cgroup will be created."; - }; - - dns = mkOption { - type = listOf str; - default = []; - description = "The dns servers to set in /etc/resolv.conf."; - }; - - dns-opt = mkOption { - type = listOf str; - default = []; - description = "dns options to set in /etc/resolv.conf."; - }; - - dns-search = mkOption { - type = listOf str; - default = []; - description = "Search domains to set in /etc/resolv.conf."; - }; - - hostname = mkOption { - type = nullOr str; - default = null; - description = "The pod hostname."; - }; - - infra = mkOption { - type = nullOr bool; - default = null; - description = "Whether to create the infra container for the pod."; - }; - - infra-command = mkOption { - type = nullOr str; - default = null; - description = "The command to run in the infra container."; - }; - - infra-image = mkOption { - type = nullOr str; - default = null; - description = "The image to use for the infra container."; - }; - - ip = mkOption { - type = nullOr str; - default = null; - description = "A static IP address for the pod network."; - }; - - # TODO: set up label file stuff. - # - # labels = mkOption {}; - - mac-address = mkOption { - type = nullOr str; - default = null; - description = "A static mac address for the pod network."; - }; - - network = mkOption { - type = nullOr str; - default = null; - description = "Network configuration for the pod."; - }; - - network-alias = mkOption { - type = nullOr str; - default = null; - description = "DNS alias for the pod."; - }; - - no-hosts = mkOption { - type = nullOr bool; - default = null; - description = "Whether to disable /etc/hosts creation for the pod."; - }; - - publish = mkOption { - type = listOf str; - default = []; - description = "List of ports to publish from the pod."; - }; - - share = mkOption { - type = listOf str; - default = []; - description = "List of kernel namespaces to share."; - }; - - containers = options.virtualisation.oci-containers.containers; - }; - }); - default = {}; - description = "Podman pods to run as systemd services."; - }; - - config = let - # Merge a list of attribute sets together - # - # TODO: See if there's a generic version for this somewhere in the - # pkgs lib? - mergeAttrs = attrList: foldr (a: b: a // b) {} attrList; - - # Create services for all defined pods - pod-services = mapAttrs' (n: v: nameValuePair "pod-${n}" (mkPod n v)) cfg; - - # Override the systemd-specific settings of containers defined in - # pods. - # - # I.e., make a systemd unit dependency on the pod service. - pod-container-services = mergeAttrs (mapAttrsToList (pname: pod: - mapAttrs' (cname: container: - nameValuePair "podman-${pname}-${cname}" rec { - after = ["pod-${pname}.service"]; - requires = after; - }) - pod.containers) - cfg); - - # Override the oci-container settings for containers defined in pods. - # - # I.e., set the --pod=podname setting, and update the dependsOn so - # it points to containers in the same pod. - podifyContainer = container: podname: - container - // { - dependsOn = - map (dependency: "${podname}-${dependency}") container.dependsOn; - extraOptions = container.extraOptions ++ ["--pod=${podname}"]; - }; - in - lib.mkIf (cfg != {}) { - virtualisation.podman.enable = true; - virtualisation.oci-containers.backend = "podman"; - - systemd.services = pod-services // pod-container-services; - - virtualisation.oci-containers.containers = mergeAttrs (mapAttrsToList - (pname: pod: - mapAttrs' (cname: container: - nameValuePair "${pname}-${cname}" (podifyContainer container pname)) - pod.containers) - cfg); - }; -}