webserver: Use a hardened systemd unit instead of a container

This commit is contained in:
Tristan Daniël Maat 2022-10-12 19:58:09 +01:00
parent b6594cea54
commit 068e6d5d77
Signed by: tlater
GPG key ID: 49670FD774E43268
6 changed files with 321 additions and 401 deletions

View file

@ -1,5 +1,4 @@
{ {
config,
pkgs, pkgs,
lib, lib,
... ...
@ -10,7 +9,6 @@
./services/webserver.nix ./services/webserver.nix
./services/starbound.nix ./services/starbound.nix
./services/postgres.nix ./services/postgres.nix
./ids.nix
./sops.nix ./sops.nix
]; ];
@ -67,30 +65,12 @@
recommendedProxySettings = true; recommendedProxySettings = true;
clientMaxBodySize = "10G"; clientMaxBodySize = "10G";
domain = "tlater.net"; 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 = { security.acme = {
email = "tm@tlater.net"; defaults.email = "tm@tlater.net";
acceptTerms = true; acceptTerms = true;
}; };
virtualisation.oci-containers.backend = "podman";
system.stateVersion = "20.09"; system.stateVersion = "20.09";
} }

View file

@ -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;
};
}

View file

@ -1,47 +1,26 @@
{ {config, ...}: let
config, domain = config.services.nginx.domain;
pkgs, in {
... services.tlaternet-webserver = {
}: { enable = true;
users = { listen = {
extraUsers.webserver = { addr = "127.0.0.1";
uid = config.ids.uids.webserver; port = 8000;
group = config.users.extraGroups.webserver.name;
isSystemUser = true;
description = "tlater.net web server user";
}; };
extraGroups.webserver = {gid = config.ids.gids.webserver;};
}; };
virtualisation.oci-containers.containers.webserver = { # Set up SSL
image = "tlaternet/webserver"; services.nginx.virtualHosts."${domain}" = let
inherit (config.services.tlaternet-webserver.listen) addr port;
imageFile = pkgs.dockerTools.buildImage {
name = "tlaternet/webserver";
tag = "latest";
contents = pkgs.tlaternet-webserver.webserver;
config = let
uid = toString config.users.extraUsers.webserver.uid;
gid = toString config.users.extraGroups.webserver.gid;
in { in {
Cmd = ["tlaternet-webserver"]; serverAliases = ["www.${domain}"];
Volumes = {"/srv/mail" = {};};
Env = [
"ROCKET_PORT=3002"
"ROCKET_TEMPLATE_DIR=${pkgs.tlaternet-templates.templates}/browser/"
];
ExposedPorts = {"3002" = {};};
User = "${uid}:${gid}";
};
};
ports = ["3002:3002"]; forceSSL = true;
volumes = ["tlaternet-mail:/srv/mail"]; enableACME = true;
extraOptions = [ extraConfig = ''
"--hostname=tlater.net" add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
# Rocket 0.4 doesn't support SIGTERM anyway, so SIGKILL is the cleanest exit possible. '';
"--stop-signal=SIGKILL"
]; locations."/".proxyPass = "http://${addr}:${toString port}";
}; };
} }

View file

@ -1,63 +1,202 @@
{ {
"nodes": { "nodes": {
"flake-utils": { "alejandra": {
"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": {
"inputs": { "inputs": {
"fenix": "fenix",
"flakeCompat": "flakeCompat",
"nixpkgs": [ "nixpkgs": [
"tlaternet-webserver", "tlaternet-webserver",
"dream2nix",
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1632266297, "lastModified": 1658427149,
"narHash": "sha256-J1yeJk6Gud9ef2pEf6aKQemrfg1pVngYDSh+SAY94xk=", "narHash": "sha256-ToD/1z/q5VHsLMrS2h96vjJoLho59eNRtknOUd19ey8=",
"owner": "nmattia", "owner": "kamadorueda",
"repo": "naersk", "repo": "alejandra",
"rev": "ee7edec50b49ab6d69b06d62f1de554efccb1ccd", "rev": "f5a22afd2adfb249b4e68e0b33aa1f0fb73fb1be",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nmattia", "owner": "kamadorueda",
"repo": "naersk", "repo": "alejandra",
"type": "github" "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": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1650522846, "lastModified": 1665321371,
"narHash": "sha256-SxWHXRI3qJwswyXAtzsi6PKVY3KLNNnb072KaJthII8=", "narHash": "sha256-0SO6MTW0bX6lxZmz1AZW/Xmk+hnTd7/hp1vF7Tp7jg0=",
"owner": "nixos", "owner": "nixos",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "6b4ebea9093c997c5f275c820e679108de4871ab", "rev": "236ba4df714131059945d7754c0aa3fbe9d2f74c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -69,51 +208,134 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1650501692, "lastModified": 1665466769,
"narHash": "sha256-ApKf0/dc0SyB7zZ6yiiOQgcXAhCXxbSDyihHfRDIzx0=", "narHash": "sha256-L+qcHpb4Ac3PipMXJY/Ktbu1+KXy23WCZ8pXWmsf7zY=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9887f024766aa27704d1f89f623efd1d063da92a", "rev": "0b20bf89e0035b6d62ad58f9db8fdbc99c2b01e8",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-21.11", "ref": "nixos-22.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "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": { "root": {
"inputs": { "inputs": {
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"tlaternet-templates": "tlaternet-templates",
"tlaternet-webserver": "tlaternet-webserver" "tlaternet-webserver": "tlaternet-webserver"
} }
}, },
"rust-overlay": { "rust-analyzer-src": {
"inputs": { "flake": false,
"flake-utils": [
"tlaternet-webserver",
"flake-utils"
],
"nixpkgs": [
"tlaternet-webserver",
"nixpkgs"
]
},
"locked": { "locked": {
"lastModified": 1633400100, "lastModified": 1657557289,
"narHash": "sha256-kHQV7jZ2vVHVI9sfda1mUROVBbQbdfKcbIpKG9WdqGo=", "narHash": "sha256-PRW+nUwuqNTRAEa83SfX+7g+g8nQ+2MMbasQ9nt6+UM=",
"owner": "oxalica", "owner": "rust-lang",
"repo": "rust-overlay", "repo": "rust-analyzer",
"rev": "9c2fc6a62ccbc6f420d71ecac6bf0b84dbbee64f", "rev": "caf23f29144b371035b864a1017dbc32573ad56d",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "oxalica", "owner": "rust-lang",
"repo": "rust-overlay", "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" "type": "github"
} }
}, },
@ -121,14 +343,15 @@
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ],
"nixpkgs-22_05": "nixpkgs-22_05"
}, },
"locked": { "locked": {
"lastModified": 1649756291, "lastModified": 1665289655,
"narHash": "sha256-KTll8bCINAzIUGaaMrbn9wb5nfhkXRLgmFrWGR/Dku0=", "narHash": "sha256-j1Q9mNBhbzeJykhObiXwEGres9qvP4vH7gxdJ+ihkLI=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "c2614c4fe61943b3d280ac1892fcebe6e8eaf8c8", "rev": "0ce0449e6404c4ff9d1b7bd657794ae5ca54deb3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -137,42 +360,20 @@
"type": "github" "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": { "tlaternet-webserver": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_2", "dream2nix": "dream2nix",
"naersk": "naersk", "fenix": "fenix_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ]
"rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1633433130, "lastModified": 1665402451,
"narHash": "sha256-jkW+HV8cJvE86gppOEXQl2ke+bDHJ7SAp8eJp8pJ0N8=", "narHash": "sha256-zWaEzUJh0WFVoaLQsMoIj2D+QFhUBJw+f+XzoYqw3es=",
"ref": "master", "ref": "master",
"rev": "1232950c06ae16bf17fb16ac1f5f2231e971936b", "rev": "6c29bc5db001e75f5ca06fec726369b87d007a03",
"revCount": 16, "revCount": 47,
"type": "git", "type": "git",
"url": "https://gitea.tlater.net/tlaternet/tlaternet.git" "url": "https://gitea.tlater.net/tlaternet/tlaternet.git"
}, },

View file

@ -2,7 +2,7 @@
description = "tlater.net host configuration"; description = "tlater.net host configuration";
inputs = { 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"; nixos-hardware.url = "github:nixos/nixos-hardware/master";
sops-nix = { sops-nix = {
url = "github:Mic92/sops-nix"; url = "github:Mic92/sops-nix";
@ -13,10 +13,6 @@
url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git"; url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
tlaternet-templates = {
url = "git+https://gitea.tlater.net/tlaternet/tlaternet-templates.git";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = { outputs = {
@ -25,16 +21,11 @@
nixos-hardware, nixos-hardware,
sops-nix, sops-nix,
tlaternet-webserver, tlaternet-webserver,
tlaternet-templates,
}: let }: let
system = "x86_64-linux"; system = "x86_64-linux";
overlays = [ overlays = [
(final: prev: { (final: prev: {
tlaternet-webserver =
tlaternet-webserver.legacyPackages.${prev.system}.packages;
tlaternet-templates =
tlaternet-templates.legacyPackages.${prev.system}.packages;
local = import ./pkgs { local = import ./pkgs {
pkgs = prev; pkgs = prev;
}; };
@ -59,6 +50,7 @@
(import ./configuration/linode.nix) (import ./configuration/linode.nix)
(import ./configuration/hardware-configuration.nix) (import ./configuration/hardware-configuration.nix)
sops-nix.nixosModules.sops sops-nix.nixosModules.sops
tlaternet-webserver.nixosModules.default
]; ];
}; };
@ -74,6 +66,7 @@
(import ./configuration) (import ./configuration)
sops-nix.nixosModules.sops sops-nix.nixosModules.sops
tlaternet-webserver.nixosModules.default
({lib, ...}: { ({lib, ...}: {
users.users.tlater.password = "insecure"; users.users.tlater.password = "insecure";

View file

@ -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);
};
}