From 536181b34a682797b5ca4ec3f0859241a2eaa11b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= <tm@tlater.net>
Date: Wed, 12 Oct 2022 19:58:09 +0100
Subject: [PATCH] webserver: Use a hardened systemd unit instead of a container

---
 configuration/default.nix            |  18 +-
 configuration/services/webserver.nix |  59 ++--
 flake.lock                           | 395 ++++++++++++++++++++-------
 flake.nix                            |  13 +-
 modules/virtualisation/pods.nix      | 222 ---------------
 5 files changed, 321 insertions(+), 386 deletions(-)
 delete mode 100644 modules/virtualisation/pods.nix

diff --git a/configuration/default.nix b/configuration/default.nix
index 7e94105..97c20a3 100644
--- a/configuration/default.nix
+++ b/configuration/default.nix
@@ -66,26 +66,10 @@
     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;
   };
 
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);
-    };
-}