From da5364df7a0cebaa4354183dd22f34c7ea94112a Mon Sep 17 00:00:00 2001 From: Aly Raffauf Date: Sun, 16 Aug 2026 21:31:31 -0400 Subject: [PATCH] nix: manage Docker networks declaratively --- .../hosts/nixos/jubilife/containers.nix | 73 ++++++------------- nix/modules/hosts/nixos/jubilife/default.nix | 1 + nix/modules/hosts/nixos/jubilife/firewall.nix | 1 - .../nixos/services/docker-networks.nix | 73 +++++++++++++++++++ 4 files changed, 95 insertions(+), 53 deletions(-) create mode 100644 nix/modules/nixos/services/docker-networks.nix diff --git a/nix/modules/hosts/nixos/jubilife/containers.nix b/nix/modules/hosts/nixos/jubilife/containers.nix index 34983637..0bc7355e 100644 --- a/nix/modules/hosts/nixos/jubilife/containers.nix +++ b/nix/modules/hosts/nixos/jubilife/containers.nix @@ -91,6 +91,27 @@ _: { ''; }; + myNixOs.docker.networks = { + immich.containers = [ + "immich-postgres" + "immich-machine-learning" + "immich-valkey" + "immich" + ]; + + nextcloud = { + containers = [ + "postgres" + "nextcloud-valkey" + "nextcloud" + "nextcloud-cron" + ]; + subnet = "172.19.0.0/16"; + bridgeInterface = "nextcloud0"; + allowedTCPPorts = [3900]; + }; + }; + virtualisation.oci-containers.containers = { dizquetv = { image = "vexorian/dizquetv:latest@sha256:98a7bc11dc5d16732c06c779ac7fd843dc4254853203f2d9dd9293b099743ca1"; @@ -316,58 +337,6 @@ _: { }; systemd.services = { - docker-network-immich = { - after = ["docker.service"]; - requires = ["docker.service"]; - - before = [ - "docker-immich-postgres.service" - "docker-immich-machine-learning.service" - "docker-immich-valkey.service" - "docker-immich.service" - ]; - - requiredBy = [ - "docker-immich-postgres.service" - "docker-immich-machine-learning.service" - "docker-immich-valkey.service" - "docker-immich.service" - ]; - - path = [pkgs.docker]; - script = "docker network inspect immich >/dev/null 2>&1 || docker network create immich"; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - }; - - docker-network-nextcloud = { - after = ["docker.service"]; - requires = ["docker.service"]; - - before = [ - "docker-postgres.service" - "docker-nextcloud-valkey.service" - "docker-nextcloud.service" - "docker-nextcloud-cron.service" - ]; - - requiredBy = [ - "docker-postgres.service" - "docker-nextcloud-valkey.service" - "docker-nextcloud.service" - "docker-nextcloud-cron.service" - ]; - - path = [pkgs.docker]; - script = "docker network inspect nextcloud >/dev/null 2>&1 || docker network create --driver bridge --subnet 172.19.0.0/16 --opt com.docker.network.bridge.name=nextcloud0 nextcloud"; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - }; - docker-dizquetv.unitConfig.RequiresMountsFor = ["/mnt/Data"]; docker-plex.unitConfig.RequiresMountsFor = [ diff --git a/nix/modules/hosts/nixos/jubilife/default.nix b/nix/modules/hosts/nixos/jubilife/default.nix index 0102f4db..36dde9c2 100644 --- a/nix/modules/hosts/nixos/jubilife/default.nix +++ b/nix/modules/hosts/nixos/jubilife/default.nix @@ -23,6 +23,7 @@ self.nixosModules.wireguardK3s self.nixosModules.lanzaboote self.nixosModules.docker + self.nixosModules.dockerNetworks self.nixosModules.alloy self.nixosModules.atbbs self.nixosModules.caddy diff --git a/nix/modules/hosts/nixos/jubilife/firewall.nix b/nix/modules/hosts/nixos/jubilife/firewall.nix index c14bb284..3574e037 100644 --- a/nix/modules/hosts/nixos/jubilife/firewall.nix +++ b/nix/modules/hosts/nixos/jubilife/firewall.nix @@ -8,7 +8,6 @@ _: { -s 10.42.0.0/16 -p tcp --dport 2049 -j ACCEPT -s 10.42.0.0/16 -p udp --dport 2049 -j ACCEPT ''; - interfaces.nextcloud0.allowedTCPPorts = [3900]; }; }; } diff --git a/nix/modules/nixos/services/docker-networks.nix b/nix/modules/nixos/services/docker-networks.nix new file mode 100644 index 00000000..7002ef51 --- /dev/null +++ b/nix/modules/nixos/services/docker-networks.nix @@ -0,0 +1,73 @@ +_: { + flake.nixosModules.dockerNetworks = { + config, + lib, + pkgs, + ... + }: let + inherit (lib) concatMapStringsSep escapeShellArg filterAttrs listToAttrs mapAttrs' mkOption nameValuePair optionals types; + + networks = config.myNixOs.docker.networks; + + mkNetworkService = name: network: let + networkArguments = + optionals (network.subnet != null) ["--subnet" network.subnet] + ++ optionals (network.bridgeInterface != null) ["--opt" "com.docker.network.bridge.name=${network.bridgeInterface}"]; + containerServices = map (container: "docker-${container}.service") network.containers; + in + nameValuePair "docker-network-${name}" { + after = ["docker.service"]; + requires = ["docker.service"]; + before = containerServices; + requiredBy = containerServices; + + path = [pkgs.docker]; + script = '' + docker network inspect ${escapeShellArg name} >/dev/null 2>&1 || \ + docker network create --driver bridge ${concatMapStringsSep " " escapeShellArg networkArguments} ${escapeShellArg name} + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + + networksWithFirewall = filterAttrs (_: network: network.bridgeInterface != null && network.allowedTCPPorts != []) networks; + in { + options.myNixOs.docker.networks = mkOption { + default = {}; + description = "Private Docker networks managed with their dependent containers."; + type = types.attrsOf (types.submodule { + options = { + containers = mkOption { + type = types.listOf types.str; + description = "Containers that require this network."; + }; + subnet = mkOption { + type = types.nullOr types.str; + default = null; + description = "Optional IPv4 subnet for a stable network gateway."; + }; + bridgeInterface = mkOption { + type = types.nullOr types.str; + default = null; + description = "Optional Linux bridge interface name."; + }; + allowedTCPPorts = mkOption { + type = types.listOf types.port; + default = []; + description = "TCP ports exposed to containers through the bridge."; + }; + }; + }); + }; + + config = { + networking.firewall.interfaces = listToAttrs (map ( + network: nameValuePair network.bridgeInterface {inherit (network) allowedTCPPorts;} + ) (builtins.attrValues networksWithFirewall)); + + systemd.services = mapAttrs' mkNetworkService networks; + }; + }; +} -- 2.51.2