summaryrefslogtreecommitdiff
path: root/sys/nspawn/dmz.nix
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-07-14 17:53:13 -0600
committerAlejandro Soto <alejandro@34project.org>2024-07-15 09:34:00 -0600
commit02abf4ed0131237c25e0a10db50fa4c41a902a50 (patch)
tree20904894fc0952806e341cdaff5941e81b3ce51c /sys/nspawn/dmz.nix
parent08e746700341dda3e3bdf704332fc3c07053d3e7 (diff)
sys: final merge of dmz, hv into sys
Diffstat (limited to 'sys/nspawn/dmz.nix')
-rw-r--r--sys/nspawn/dmz.nix160
1 files changed, 160 insertions, 0 deletions
diff --git a/sys/nspawn/dmz.nix b/sys/nspawn/dmz.nix
new file mode 100644
index 0000000..080b32d
--- /dev/null
+++ b/sys/nspawn/dmz.nix
@@ -0,0 +1,160 @@
+{ lib, config, flakes, pkgs, ... }:
+with lib; let
+ cfg = config.local.nspawn.dmz;
+ inherit (config.local) mailHost;
+in
+{
+ options.local.nspawn.dmz = with types; {
+ enable = mkEnableOption "DMZ services in a container";
+
+ net = mkOption {
+ type = str;
+ };
+
+ netBits = mkOption {
+ type = int;
+ };
+
+ hostAddr = mkOption {
+ type = str;
+ };
+
+ system = mkOption {
+ type = attrs;
+ };
+ };
+
+ # Situación con os-release
+ #
+ # La idea aquí es poder hacer 'btrfs subvol create /var/lib/machines/foo' y
+ # dejar que systemd-nspawn y el activation script creen todo lo demás. Esto
+ # no sirve bien debido a la prueba barata que hace systemd para revisar si el
+ # árbol parece contener una imagen de sistema operativo. Esta prueba falla en
+ # dos momentos distintos:
+ #
+ # 1. Inmediatamente tras crear un árbol vacío, puesto que os-release no existe.
+ # La solución naive es 'mkdir rootfs/etc && touch rootfs/etc/os-release'.
+ #
+ # 2. Luego de reiniciar el contenedor una vez que NixOS ha preparado /etc, ya que
+ # systemd espera un archivo regular y no telera el symlink a la store.
+ #
+ # Resulta ser que systemd revisa tanto /etc/os-release como /usr/lib/os-release.
+ # NixOS evidentemente no usa la segunda ruta por ser FHS, así que la duct tape
+ # final es 'mkdir rootfs/usr/lib && touch rootfs/usr/lib/os-release'.
+
+ config = mkIf cfg.enable {
+ local = {
+ mailHost = {
+ mdaListen = cfg.hostAddr;
+ saslPort = 11000;
+ lmtpPort = 11001;
+ };
+
+ nspawn.dmz = {
+ system =
+ let
+ containerModule = { ... }: {
+ #TODO: urgente: bloquear puertos de dovecot a non-postfix con iptables
+ config = {
+ local = {
+ preset.dmz = {
+ enable = true;
+ container = true;
+ };
+
+ mta = {
+ mdaAddr = mailHost.mdaListen;
+ inherit (mailHost) saslPort lmtpPort;
+ };
+ };
+
+ nixpkgs = {
+ pkgs = mkDefault pkgs;
+ localSystem = mkDefault pkgs.stdenv.hostPlatform;
+ };
+ };
+ };
+ in
+ # Tomado de la definición de pkgs.nixos junto con definición de nixpkgs.{pkgs,localSystem} arriba
+ import "${flakes.nixpkgs}/nixos/lib/eval-config.nix" {
+ modules = [
+ ../.
+ containerModule
+ ];
+
+ system = null;
+ specialArgs = { inherit flakes; };
+ };
+
+ net = "10.34.3.0";
+ netBits = 28;
+ hostAddr = "10.34.3.1";
+ };
+ };
+
+ systemd = {
+ nspawn.dmz = {
+ execConfig.PrivateUsers = "pick";
+
+ filesConfig.BindReadOnly = [
+ # idmap porque algunos hacks en nixpkgs (postfix-setup.service)
+ # asumen que la store es de root
+ "/nix/store:/nix/store:idmap"
+ "${cfg.system.config.system.build.toplevel}/init:/sbin/init"
+ ];
+
+ networkConfig.Port = [
+ "tcp:25"
+ "tcp:80"
+ "tcp:443"
+ "tcp:465"
+ "tcp:587"
+ ];
+ };
+
+ network.networks."40-ve-dmz" = {
+ matchConfig = {
+ Name = "ve-dmz";
+ Driver = "veth";
+ };
+
+ networkConfig = {
+ Address = "${cfg.hostAddr}/${toString cfg.netBits}";
+ LinkLocalAddressing = "yes";
+ DHCPServer = "yes";
+ IPMasquerade = "both";
+ LLDP = "yes";
+ EmitLLDP = "customer-bridge";
+ IPv6SendRA = "yes";
+ };
+
+ # IP de contenedor fijada en hostAddr + 1
+ dhcpServerConfig = {
+ PoolOffset = 2;
+ PoolSize = 1;
+ };
+ };
+
+ services = {
+ dovecot2.after = [ "systemd-nspawn@dmz.service" ];
+
+ "systemd-nspawn@dmz" = {
+ overrideStrategy = "asDropin";
+
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+ wantedBy = [ "machines.target" ];
+ };
+ };
+ };
+
+ networking.firewall = {
+ allowedTCPPorts = [ 25 80 443 ];
+
+ interfaces.ve-dmz = {
+ allowedTCPPorts = [ mailHost.saslPort mailHost.lmtpPort ];
+ allowedUDPPorts = [ 67 ]; # DHCP
+ };
+ };
+ };
+}