From 232c9aa946483436525ac324d58dbf61e51ee365 Mon Sep 17 00:00:00 2001 From: SebastianStork Date: Sat, 14 Jun 2025 01:13:37 +0200 Subject: [PATCH] Add uniqueness check for ports Credit to https://lorenzbischof.ch/posts/detect-port-conflicts-in-nixos-services/ --- hosts/alto/default.nix | 1 + hosts/alto/hardware.nix | 1 - hosts/cirrus/default.nix | 1 + hosts/cirrus/hardware.nix | 1 - hosts/cumulus/default.nix | 1 + hosts/cumulus/hardware.nix | 1 - hosts/north/default.nix | 1 + hosts/north/hardware.nix | 2 - modules/system/meta/ports.nix | 50 +++++++++++++++++++ .../system/services/actualbudget/default.nix | 2 + modules/system/services/caddy.nix | 14 +++--- modules/system/services/crowdsec/default.nix | 14 +++++- modules/system/services/forgejo/default.nix | 2 + modules/system/services/forgejo/ssh.nix | 2 + modules/system/services/hedgedoc/default.nix | 2 + modules/system/services/nextcloud/default.nix | 2 + modules/system/services/ntfy.nix | 2 + modules/system/services/resolved.nix | 14 ++++++ modules/system/services/syncthing/default.nix | 5 ++ modules/system/services/tailscale.nix | 2 + .../system/services/uptime-kuma/default.nix | 2 + 21 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 modules/system/meta/ports.nix create mode 100644 modules/system/services/resolved.nix diff --git a/hosts/alto/default.nix b/hosts/alto/default.nix index e1973c4..2e852cf 100644 --- a/hosts/alto/default.nix +++ b/hosts/alto/default.nix @@ -9,6 +9,7 @@ users.seb.enable = true; services = { + resolved.enable = true; tailscale = { enable = true; ssh.enable = true; diff --git a/hosts/alto/hardware.nix b/hosts/alto/hardware.nix index 8539219..a0ae9d1 100644 --- a/hosts/alto/hardware.nix +++ b/hosts/alto/hardware.nix @@ -39,5 +39,4 @@ linkConfig.RequiredForOnline = "routable"; }; }; - services.resolved.enable = true; } diff --git a/hosts/cirrus/default.nix b/hosts/cirrus/default.nix index 8f46b21..4620657 100644 --- a/hosts/cirrus/default.nix +++ b/hosts/cirrus/default.nix @@ -9,6 +9,7 @@ users.seb.enable = true; services = { + resolved.enable = true; tailscale = { enable = true; ssh.enable = true; diff --git a/hosts/cirrus/hardware.nix b/hosts/cirrus/hardware.nix index 72446a5..1e905e3 100644 --- a/hosts/cirrus/hardware.nix +++ b/hosts/cirrus/hardware.nix @@ -44,5 +44,4 @@ ]; }; }; - services.resolved.enable = true; } diff --git a/hosts/cumulus/default.nix b/hosts/cumulus/default.nix index 6ec811b..cc19f2b 100644 --- a/hosts/cumulus/default.nix +++ b/hosts/cumulus/default.nix @@ -9,6 +9,7 @@ users.seb.enable = true; services = { + resolved.enable = true; tailscale = { enable = true; ssh.enable = true; diff --git a/hosts/cumulus/hardware.nix b/hosts/cumulus/hardware.nix index 00772cf..1ff17ba 100644 --- a/hosts/cumulus/hardware.nix +++ b/hosts/cumulus/hardware.nix @@ -44,5 +44,4 @@ ]; }; }; - services.resolved.enable = true; } diff --git a/hosts/north/default.nix b/hosts/north/default.nix index 41be11d..a724a65 100644 --- a/hosts/north/default.nix +++ b/hosts/north/default.nix @@ -22,6 +22,7 @@ sound.enable = true; services = { + resolved.enable = true; gc.enable = true; geoclue.enable = true; tailscale = { diff --git a/hosts/north/hardware.nix b/hosts/north/hardware.nix index d5d1b9f..16e8926 100644 --- a/hosts/north/hardware.nix +++ b/hosts/north/hardware.nix @@ -35,8 +35,6 @@ udev.extraRules = '' ACTION=="add" SUBSYSTEM=="pci" ATTR{vendor}=="0x1022" ATTR{device}=="0x43ee" ATTR{power/wakeup}="disabled" ''; - - resolved.enable = true; }; networking.useNetworkd = true; diff --git a/modules/system/meta/ports.nix b/modules/system/meta/ports.nix new file mode 100644 index 0000000..45b55b4 --- /dev/null +++ b/modules/system/meta/ports.nix @@ -0,0 +1,50 @@ +{ + config, + options, + lib, + ... +}: +let + cfg = config.meta.ports; + + duplicatedPorts = + options.meta.ports.list.definitionsWithLocations + |> lib.concatMap ( + entry: + map (port: { + file = entry.file; + port = port; + }) entry.value + ) + |> lib.groupBy (entry: toString entry.port) + |> lib.filterAttrs (port: entries: lib.length entries > 1); + + errorMessage = + duplicatedPorts + |> lib.mapAttrsToList ( + port: entries: + "Duplicate port ${port} found in:\n" + lib.concatMapStrings (entry: " - ${entry.file}\n") entries + ) + |> lib.concatStrings; +in +{ + options.meta.ports = { + list = lib.mkOption { + type = lib.types.listOf lib.types.port; + default = [ ]; + internal = true; + }; + assertUnique = lib.mkEnableOption "" // { + default = true; + }; + }; + + config = lib.mkIf cfg.assertUnique { + assertions = [ + { + assertion = duplicatedPorts == { }; + message = errorMessage; + } + ]; + }; +} diff --git a/modules/system/services/actualbudget/default.nix b/modules/system/services/actualbudget/default.nix index 2ffbf70..05769da 100644 --- a/modules/system/services/actualbudget/default.nix +++ b/modules/system/services/actualbudget/default.nix @@ -16,6 +16,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ cfg.port ]; + users = { groups.actual = { }; users.actual = { diff --git a/modules/system/services/caddy.nix b/modules/system/services/caddy.nix index 1d87b8f..ec2fb31 100644 --- a/modules/system/services/caddy.nix +++ b/modules/system/services/caddy.nix @@ -27,6 +27,11 @@ let reverse_proxy localhost:${toString port} ''; }; + + ports = [ + 80 + 443 + ]; in { options.custom.services.caddy.virtualHosts = lib.mkOption { @@ -57,6 +62,9 @@ in config = lib.mkIf (virtualHosts != { }) ( lib.mkMerge [ { + meta.ports.list = lib.mkIf nonTailscaleHostsExist ports; + networking.firewall.allowedTCPPorts = lib.mkIf nonTailscaleHostsExist ports; + services.caddy = { enable = true; enableReload = false; @@ -66,11 +74,6 @@ in _: value: lib.nameValuePair value.domain (mkVirtualHostConfig value.domain value.port) ); }; - - networking.firewall.allowedTCPPorts = lib.mkIf nonTailscaleHostsExist [ - 80 - 443 - ]; } (lib.mkIf tailscaleHostsExist { @@ -78,7 +81,6 @@ in services.caddy = { package = caddyWithTailscale; - enableReload = false; globalConfig = '' admin off diff --git a/modules/system/services/crowdsec/default.nix b/modules/system/services/crowdsec/default.nix index 8817917..1195564 100644 --- a/modules/system/services/crowdsec/default.nix +++ b/modules/system/services/crowdsec/default.nix @@ -19,6 +19,10 @@ in type = lib.types.port; default = 8080; }; + prometheusPort = lib.mkOption { + type = lib.types.port; + default = 6060; + }; sources = lib.mkOption { type = lib.types.listOf ( lib.types.enum [ @@ -32,6 +36,11 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ + cfg.apiPort + cfg.prometheusPort + ]; + nixpkgs.overlays = [ inputs.crowdsec.overlays.default ]; sops.secrets."crowdsec/enrollment-key".owner = user; @@ -42,7 +51,10 @@ in enable = true; package = inputs.crowdsec.packages.${pkgs.system}.crowdsec; enrollKeyFile = config.sops.secrets."crowdsec/enrollment-key".path; - settings.api.server.listen_uri = "127.0.0.1:${toString cfg.apiPort}"; + settings = { + api.server.listen_uri = "127.0.0.1:${toString cfg.apiPort}"; + cscli.prometheus_uri = "http://127.0.0.1:${toString cfg.prometheusPort}"; + }; allowLocalJournalAccess = true; acquisitions = diff --git a/modules/system/services/forgejo/default.nix b/modules/system/services/forgejo/default.nix index 6748240..96cb536 100644 --- a/modules/system/services/forgejo/default.nix +++ b/modules/system/services/forgejo/default.nix @@ -24,6 +24,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ cfg.port ]; + sops.secrets."forgejo/admin-password".owner = user; services.forgejo = { diff --git a/modules/system/services/forgejo/ssh.nix b/modules/system/services/forgejo/ssh.nix index cafacc4..d6b0590 100644 --- a/modules/system/services/forgejo/ssh.nix +++ b/modules/system/services/forgejo/ssh.nix @@ -12,6 +12,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ cfg.port ]; + services.forgejo.settings.server.SSH_PORT = cfg.port; services.openssh = { diff --git a/modules/system/services/hedgedoc/default.nix b/modules/system/services/hedgedoc/default.nix index d9b4ea0..d144347 100644 --- a/modules/system/services/hedgedoc/default.nix +++ b/modules/system/services/hedgedoc/default.nix @@ -25,6 +25,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ cfg.port ]; + sops = { secrets = { "hedgedoc/seb-password".owner = user; diff --git a/modules/system/services/nextcloud/default.nix b/modules/system/services/nextcloud/default.nix index 50f2eae..0300909 100644 --- a/modules/system/services/nextcloud/default.nix +++ b/modules/system/services/nextcloud/default.nix @@ -25,6 +25,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ cfg.port ]; + sops.secrets."nextcloud/admin-password".owner = user; services.nextcloud = { diff --git a/modules/system/services/ntfy.nix b/modules/system/services/ntfy.nix index d2411e6..b86f47a 100644 --- a/modules/system/services/ntfy.nix +++ b/modules/system/services/ntfy.nix @@ -16,6 +16,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ cfg.port ]; + services.ntfy-sh = { enable = true; settings = { diff --git a/modules/system/services/resolved.nix b/modules/system/services/resolved.nix new file mode 100644 index 0000000..0aa0a17 --- /dev/null +++ b/modules/system/services/resolved.nix @@ -0,0 +1,14 @@ +{ config, lib, ... }: +{ + options.custom.services.resolved.enable = lib.mkEnableOption ""; + + config = lib.mkIf config.custom.services.resolved.enable { + meta.ports.list = [ + 53 + 5353 + 5355 + ]; + + services.resolved.enable = true; + }; +} diff --git a/modules/system/services/syncthing/default.nix b/modules/system/services/syncthing/default.nix index 9b71e1c..5cea27a 100644 --- a/modules/system/services/syncthing/default.nix +++ b/modules/system/services/syncthing/default.nix @@ -40,6 +40,11 @@ in } ]; + meta.ports.list = [ + cfg.syncPort + cfg.gui.port + ]; + services.syncthing = { enable = true; diff --git a/modules/system/services/tailscale.nix b/modules/system/services/tailscale.nix index 9a16760..2c5842c 100644 --- a/modules/system/services/tailscale.nix +++ b/modules/system/services/tailscale.nix @@ -14,6 +14,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ config.services.tailscale.port ]; + sops.secrets."tailscale-auth-key" = { }; services.tailscale = { diff --git a/modules/system/services/uptime-kuma/default.nix b/modules/system/services/uptime-kuma/default.nix index b9b26a1..116bb2f 100644 --- a/modules/system/services/uptime-kuma/default.nix +++ b/modules/system/services/uptime-kuma/default.nix @@ -16,6 +16,8 @@ in }; config = lib.mkIf cfg.enable { + meta.ports.list = [ cfg.port ]; + services.uptime-kuma = { enable = true; settings.PORT = toString cfg.port;