Fix duplicate port check

This commit is contained in:
Jakob Lechner 2025-04-10 01:13:11 +02:00
parent 48e71f75f8
commit 6f01431032
39 changed files with 132 additions and 158 deletions

View file

@ -1,33 +1,5 @@
{ lib, ... }: { lib, ... }:
let
filterPort = pm: port: (
lib.attrsets.catAttrs port (
lib.attrsets.attrValues (
lib.attrsets.filterAttrs (_: v: v ? "${port}") pm
)
)
);
onlyUniqueItemsInList = x: lib.lists.length x == lib.lists.length (lib.lists.unique x);
protocols = x: lib.lists.unique (lib.flatten (map builtins.attrNames (lib.attrValues x)));
mkRange = x: lib.lists.range (builtins.elemAt x 0) (builtins.elemAt x 1);
validateList = allowed: builtins.all (x: builtins.elem x allowed);
in
{ {
validatePortAttrset = portmap: validatePortAttrset = import ./ports.nix { inherit lib; };
if ! onlyUniqueItemsInList (lib.flatten (map
(x:
if lib.isInt x then x
else if lib.isList x then x
else if lib.isAttrs x then
(
if ! validateList [ "range" ] (builtins.attrNames x) then builtins.abort "found invalid attribute name"
else if x ? "range" then if lib.lists.length x.range == 2 then mkRange x.range else builtins.abort "range needs a list with exactly two items"
else builtins.abort "found invalid attrset"
)
else builtins.abort "found invalid entry in portmap"
)
(filterPort portmap "udp"))) then builtins.abort "Found duplicate ports."
else if ! validateList [ "tcp" "udp" ] (protocols portmap) then builtins.abort "Found invalid protocol."
else portmap;
} }

View file

@ -9,25 +9,25 @@ let
) )
); );
onlyUniqueItemsInList = x: lib.lists.length x == lib.lists.length (lib.lists.unique x); onlyUniqueItemsInList = x: lib.lists.length x == lib.lists.length (lib.lists.unique x);
protocols = x: lib.lists.unique (lib.flatten (map builtins.attrNames (lib.attrValues x))); mkRange = { from, to }: (lib.lists.range from to);
mkRange = x: lib.lists.range (builtins.elemAt x 0) (builtins.elemAt x 1);
validateList = allowed: builtins.all (x: builtins.elem x allowed);
in in
{ portmap:
validatePortAttrset = portmap: if builtins.all
if ! onlyUniqueItemsInList (lib.flatten (map (
proto:
if onlyUniqueItemsInList
(
lib.flatten (
map
(x: (x:
if lib.isInt x then x if lib.isInt x then x
else if lib.isList x then x else if lib.isList x then x
else if lib.isAttrs x then else if lib.isAttrs x then mkRange x
(
if ! validateList [ "range" ] (builtins.attrNames x) then builtins.abort "found invalid attribute name"
else if x ? "range" then if lib.lists.length x.range == 2 then mkRange x.range else builtins.abort "range needs a list with exactly two items"
else builtins.abort "found invalid attrset"
)
else builtins.abort "found invalid entry in portmap" else builtins.abort "found invalid entry in portmap"
) )
(filterPort portmap "udp"))) then builtins.abort "Found duplicate ports." (filterPort portmap proto)
else if ! validateList [ "tcp" "udp" ] (protocols portmap) then builtins.abort "Found invalid protocol." )
else portmap; ) then true else builtins.abort "Found duplicate ${proto} ports."
} ) [ "tcp" "udp" ]
then portmap
else builtins.abort "Found duplicate ports."

View file

@ -5,6 +5,7 @@
./hardware-configuration.nix ./hardware-configuration.nix
../../users/jalr ../../users/jalr
./services ./services
./ports.nix
]; ];
services.openssh.enable = true; services.openssh.enable = true;

View file

@ -1,7 +1,8 @@
{ custom-utils, ... }: { custom-utils, ... }:
custom-utils.validatePortAttrset { {
asterisk-rtp = { udp.range = [ 10000 10200 ]; }; config.networking.ports = custom-utils.validatePortAttrset {
asterisk-rtp.udp = { from = 10000; to = 10200; };
doorbell-audiosocket.tcp = 9092; doorbell-audiosocket.tcp = 9092;
doorbell-webrtc-ice.tcp = 8189; doorbell-webrtc-ice.tcp = 8189;
doorbell-webrtc.tcp = 8889; doorbell-webrtc.tcp = 8889;
@ -11,4 +12,5 @@ custom-utils.validatePortAttrset {
nginx-https.tcp = 443; nginx-https.tcp = 443;
unifi-inform.tcp = 8080; unifi-inform.tcp = 8080;
unifi-ui.tcp = 8443; unifi-ui.tcp = 8443;
};
} }

View file

@ -1,16 +1,12 @@
args@{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
ports = import ../../ports.nix args; inherit (config.networking) ports;
secretConfigFiles = [ secretConfigFiles = [
"ari" "ari"
"pjsip" "pjsip"
"voicemail" "voicemail"
]; ];
rtp = {
start = builtins.elemAt ports.asterisk-rtp.udp.range 0;
end = builtins.elemAt ports.asterisk-rtp.udp.range 1;
};
voicemail-sounds = pkgs.callPackage ./voicemail-sounds { }; voicemail-sounds = pkgs.callPackage ./voicemail-sounds { };
in in
{ {
@ -142,8 +138,8 @@ in
''; '';
"rtp.conf" = '' "rtp.conf" = ''
[general] [general]
rtpstart=${toString rtp.start} rtpstart=${toString ports.asterisk-rtp.udp.from}
rtpend=${toString rtp.end} rtpend=${toString ports.asterisk-rtp.udp.to}
''; '';
"dnsmgr.conf" = '' "dnsmgr.conf" = ''
[general] [general]
@ -167,12 +163,7 @@ in
(lib.listToAttrs (map (name: lib.nameValuePair name { }) secretConfigFiles)); (lib.listToAttrs (map (name: lib.nameValuePair name { }) secretConfigFiles));
networking.firewall = { networking.firewall = {
allowedUDPPortRanges = [ allowedUDPPortRanges = lib.singleton ports.asterisk-rtp.udp;
{
from = rtp.start;
to = rtp.end;
}
];
interfaces.voice = { interfaces.voice = {
allowedTCPPorts = [ 5060 ]; allowedTCPPorts = [ 5060 ];
allowedUDPPorts = [ 5060 ]; allowedUDPPorts = [ 5060 ];

View file

@ -1,7 +1,7 @@
args@{ config, ... }: { config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
sops.secrets.myintercom-doorbell-password = { sops.secrets.myintercom-doorbell-password = {

View file

@ -1,6 +1,6 @@
args@{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
ports = import ../../ports.nix args; inherit (config.networking) ports;
cfgdir = pkgs.stdenvNoCC.mkDerivation { cfgdir = pkgs.stdenvNoCC.mkDerivation {
name = "esphome-config"; name = "esphome-config";
src = ./devices; src = ./devices;

View file

@ -1,6 +1,6 @@
args@{ pkgs, config, ... }: { pkgs, config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
services.home-assistant = { services.home-assistant = {

View file

@ -1,7 +1,7 @@
args: { config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
services.nginx = { services.nginx = {

View file

@ -1,7 +1,7 @@
args@{ pkgs, ... }: { config, pkgs, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
services.unifi = { services.unifi = {

View file

@ -34,6 +34,7 @@ with lib; {
imports = [ imports = [
../../users/jalr ../../users/jalr
./services ./services
./ports.nix
]; ];
config = { config = {
system.stateVersion = "23.11"; system.stateVersion = "23.11";

View file

@ -1,6 +1,7 @@
{ custom-utils, ... }: { custom-utils, ... }:
custom-utils.validatePortAttrset { {
config.networking.ports = custom-utils.validatePortAttrset {
calibre-server.tcp = 8081; calibre-server.tcp = 8081;
calibre-web.tcp = 8082; calibre-web.tcp = 8082;
esphome.tcp = 6052; esphome.tcp = 6052;
@ -14,7 +15,7 @@ custom-utils.validatePortAttrset {
nginx-http.tcp = 80; nginx-http.tcp = 80;
nginx-https.tcp = 443; nginx-https.tcp = 443;
postfix-relay.tcp = 25; postfix-relay.tcp = 25;
postfix-submission.tcp = [ 465 ]; postfix-submission.tcp = 465;
qbittorrent-torrent.tcp = 59832; qbittorrent-torrent.tcp = 59832;
qbittorrent-webui.tcp = 8099; qbittorrent-webui.tcp = 8099;
radicale.tcp = 5232; radicale.tcp = 5232;
@ -25,4 +26,5 @@ custom-utils.validatePortAttrset {
unifi-http.tcp = 8080; unifi-http.tcp = 8080;
unifi-https.tcp = 8443; unifi-https.tcp = 8443;
wireguard-public-ip-tunnel.udp = 51000; wireguard-public-ip-tunnel.udp = 51000;
};
} }

View file

@ -1,6 +1,6 @@
args@{ lib, config, ... }: { lib, config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
sops.secrets.calibre-htpasswd = { sops.secrets.calibre-htpasswd = {

View file

@ -1,6 +1,6 @@
args@{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
ports = import ../../ports.nix args; inherit (config.networking) ports;
cfgdir = pkgs.stdenvNoCC.mkDerivation { cfgdir = pkgs.stdenvNoCC.mkDerivation {
name = "esphome-config"; name = "esphome-config";
src = ./devices; src = ./devices;

View file

@ -1,6 +1,6 @@
args@{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
interfaces = import ../interfaces.nix; interfaces = import ../interfaces.nix;
domain = "hass.jalr.de"; domain = "hass.jalr.de";
in in

View file

@ -1,6 +1,6 @@
args@{ lib, ... }: { config, lib, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
services.jellyfin = { services.jellyfin = {

View file

@ -1,7 +1,7 @@
args: { config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
#sops.secrets."domain_key_jalr.de" = { #sops.secrets."domain_key_jalr.de" = {

View file

@ -1,7 +1,7 @@
args@{ config, pkgs, ... }: { config, pkgs, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
signalPhoneNumber = "+4915566437153"; signalPhoneNumber = "+4915566437153";
signalUser = "jalr"; signalUser = "jalr";
in in

View file

@ -1,7 +1,7 @@
args@{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
settings = { settings = {
# https://www.navidrome.org/docs/usage/configuration-options/#available-options # https://www.navidrome.org/docs/usage/configuration-options/#available-options
Address = "127.0.0.1"; Address = "127.0.0.1";

View file

@ -1,7 +1,7 @@
args: { config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
services.nginx = { services.nginx = {

View file

@ -1,7 +1,7 @@
args@{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
listenPort = ports.wireguard-public-ip-tunnel.udp; listenPort = ports.wireguard-public-ip-tunnel.udp;
remoteHost = "magnesium.jalr.de"; remoteHost = "magnesium.jalr.de";
remotePort = 51000; remotePort = 51000;

View file

@ -1,7 +1,7 @@
args@{ config, ... }: { config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
sops.secrets.radicale-htpasswd = { sops.secrets.radicale-htpasswd = {

View file

@ -1,6 +1,6 @@
args@{ lib, config, pkgs, ... }: { lib, config, pkgs, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
domain = "rmfakecloud.jalr.de"; domain = "rmfakecloud.jalr.de";
cfg = config.services.rmfakecloud; cfg = config.services.rmfakecloud;
mkEnvironment = settings: lib.strings.concatLines ( mkEnvironment = settings: lib.strings.concatLines (

View file

@ -1,6 +1,6 @@
args@{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
ports = import ../../ports.nix args; inherit (config.networking) ports;
interfaces = import ../../interfaces.nix; interfaces = import ../../interfaces.nix;
in in
{ {

View file

@ -1,7 +1,7 @@
args: { config, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
in in
{ {
jalr.qbittorrent = { jalr.qbittorrent = {

View file

@ -1,7 +1,7 @@
args@{ pkgs, ... }: { config, pkgs, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
interfaces = import ../interfaces.nix; interfaces = import ../interfaces.nix;
in in
{ {

View file

@ -1,7 +1,7 @@
args@{ pkgs, ... }: { config, pkgs, ... }:
let let
ports = import ../ports.nix args; inherit (config.networking) ports;
shutdownAndroidVm = pkgs.writeShellScript "shutdown-android-vm" '' shutdownAndroidVm = pkgs.writeShellScript "shutdown-android-vm" ''
set -e set -e
export PATH=${pkgs.lib.makeBinPath [pkgs.libvirt pkgs.gnused pkgs.android-tools]} export PATH=${pkgs.lib.makeBinPath [pkgs.libvirt pkgs.gnused pkgs.android-tools]}

View file

@ -1,5 +1,7 @@
{ custom-utils, ... }:
{ {
config.networking.ports = { config.networking.ports = custom-utils.validatePortAttrset {
coturn-cli.tcp = 5766; coturn-cli.tcp = 5766;
coturn-plain = { tcp = [ 3478 3479 ]; udp = [ 3478 3479 ]; }; coturn-plain = { tcp = [ 3478 3479 ]; udp = [ 3478 3479 ]; };
coturn-relay.udp = { from = 49160; to = 49200; }; coturn-relay.udp = { from = 49160; to = 49200; };

View file

@ -3,7 +3,7 @@
let let
cfg = config.services.coturn; cfg = config.services.coturn;
fqdn = "turn.jalr.de"; fqdn = "turn.jalr.de";
ports = config.networking.ports; inherit (config.networking) ports;
in in
{ {
sops.secrets.turn-static-auth-secret = { sops.secrets.turn-static-auth-secret = {

View file

@ -2,7 +2,7 @@
let let
domain = "git.jalr.de"; domain = "git.jalr.de";
cfg = config.services.forgejo; cfg = config.services.forgejo;
ports = config.networking.ports; inherit (config.networking) ports;
in in
{ {
sops.secrets.forgejo-mail = { sops.secrets.forgejo-mail = {

View file

@ -3,7 +3,7 @@
let let
domain = "pad.jalr.de"; domain = "pad.jalr.de";
cfg = config.services.hedgedoc; cfg = config.services.hedgedoc;
ports = config.networking.ports; inherit (config.networking) ports;
in in
{ {
sops.secrets.hedgedoc-session-secret = { sops.secrets.hedgedoc-session-secret = {

View file

@ -3,7 +3,7 @@ let
cfg = config.services.ntfy-sh; cfg = config.services.ntfy-sh;
domain = "ntfy.jalr.de"; domain = "ntfy.jalr.de";
datadir = "/var/lib/ntfy-sh"; datadir = "/var/lib/ntfy-sh";
ports = config.networking.ports; inherit (config.networking) ports;
in in
{ {
# ntfy access --auth-file /var/lib/private/ntfy-sh/user.db '*' 'up*' write-only # ntfy access --auth-file /var/lib/private/ntfy-sh/user.db '*' 'up*' write-only

View file

@ -3,7 +3,7 @@
let let
listenPort = ports.wireguard-public-ip-tunnel.udp; listenPort = ports.wireguard-public-ip-tunnel.udp;
publicKey = "GCmQs7upvDYFueEfqD2yJkkOZg3K7YaGluWWzdjsyTo="; publicKey = "GCmQs7upvDYFueEfqD2yJkkOZg3K7YaGluWWzdjsyTo=";
ports = config.networking.ports; inherit (config.networking) ports;
in in
{ {
sops.secrets = lib.listToAttrs (map sops.secrets = lib.listToAttrs (map

View file

@ -2,7 +2,7 @@
let let
domain = "notes.jalr.de"; domain = "notes.jalr.de";
ports = config.networking.ports; inherit (config.networking) ports;
in in
{ {
services.trilium-server = { services.trilium-server = {

View file

@ -3,7 +3,7 @@
let let
domain = "jalr.de"; domain = "jalr.de";
matrixDomain = "matrix.jalr.de"; matrixDomain = "matrix.jalr.de";
ports = config.networking.ports; inherit (config.networking) ports;
in in
{ {
networking.firewall.allowedTCPPorts = [ ports.nginx-http.tcp ports.nginx-https.tcp ]; networking.firewall.allowedTCPPorts = [ ports.nginx-http.tcp ports.nginx-https.tcp ];

View file

@ -3,6 +3,7 @@
./hardware-configuration.nix ./hardware-configuration.nix
../../users/jalr ../../users/jalr
./services ./services
./ports.nix
]; ];
networking.hostName = "weinturm-pretix-prod"; networking.hostName = "weinturm-pretix-prod";

View file

@ -1,8 +1,10 @@
{ custom-utils, ... }: { custom-utils, ... }:
custom-utils.validatePortAttrset { {
config.networking.ports = custom-utils.validatePortAttrset {
nginx-http.tcp = 80; nginx-http.tcp = 80;
nginx-https.tcp = 443; nginx-https.tcp = 443;
ports.postfix-relay.tcp = 25; postfix-relay.tcp = 25;
ports.postfix-submission.tcp = [ 465 ]; postfix-submission.tcp = 465;
};
} }

View file

@ -1,8 +1,8 @@
args@{ config, lib, ... }: { config, lib, ... }:
let let
cfg = config.services.pretix; cfg = config.services.pretix;
ports = import ../ports.nix args; inherit (config.networking) ports;
domain = "tickets.weinturm-open-air.de"; domain = "tickets.weinturm-open-air.de";
extraDomains = [ extraDomains = [
"tickets.weinturm.jalr.de" "tickets.weinturm.jalr.de"

View file

@ -1,16 +1,16 @@
{lib, ...}: { lib, ... }:
{ {
options.networking.ports = with lib; with lib.types; mkOption { options.networking.ports = with lib; with lib.types; mkOption {
type = attrsOf (types.submodule { type = attrsOf (types.submodule {
options = { options = {
tcp = mkOption { tcp = mkOption {
type = oneOf [ port (listOf port) (attrsOf port) (listOf (attrsOf lib.types.port)) ]; type = oneOf [ port (listOf port) (attrsOf port) ];
description = "TCP ports"; description = "TCP ports";
default = [ ]; default = [ ];
}; };
udp = mkOption { udp = mkOption {
type = oneOf [ port (listOf port) (attrsOf port) (listOf (attrsOf lib.types.port)) ]; type = oneOf [ port (listOf port) (attrsOf port) ];
description = "UDP ports"; description = "UDP ports";
default = [ ]; default = [ ];
}; };