From ffe8e4acf6e4d11ebd387d6126884dc3a9cde499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Nov 2025 05:20:09 +0800 Subject: [PATCH 01/10] test(nginx): Add simple tests to assert nginx features work --- checks/default.nix | 2 + configuration/default.nix | 2 +- configuration/nginx/default.nix | 18 +++++---- configuration/nginx/logging.nix | 58 +++++++++++++++++++++++++++- configuration/nginx/ssl.nix | 68 +++++++++++++++++++++++++++++++++ modules/default.nix | 7 +++- modules/serviceTests/mocks.nix | 27 +++++++++++++ modules/serviceTests/stub.nix | 20 ++++++++++ 8 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 modules/serviceTests/mocks.nix create mode 100644 modules/serviceTests/stub.nix diff --git a/checks/default.nix b/checks/default.nix index 674b19d..737313d 100644 --- a/checks/default.nix +++ b/checks/default.nix @@ -6,6 +6,8 @@ let in { x86_64-linux = lib.mergeAttrsList [ + flake-inputs.self.nixosConfigurations.hetzner-1.config.serviceTests + { nix = checkLib.mkLint { name = "nix-lints"; diff --git a/configuration/default.nix b/configuration/default.nix index 9881db2..6f73f54 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -11,7 +11,7 @@ flake-inputs.tlaternet-webserver.nixosModules.default "${modulesPath}/profiles/minimal.nix" - (import ../modules) + ../modules ./services/backups.nix ./services/battery-manager.nix diff --git a/configuration/nginx/default.nix b/configuration/nginx/default.nix index dab0259..92ea53c 100644 --- a/configuration/nginx/default.nix +++ b/configuration/nginx/default.nix @@ -10,13 +10,15 @@ description = "The base domain name to append to virtual domain names"; }; - config.services.nginx = { - enable = true; - recommendedTlsSettings = true; - recommendedOptimisation = true; - recommendedGzipSettings = true; - recommendedProxySettings = true; - clientMaxBodySize = "10G"; - statusPage = true; # For metrics, should be accessible only from localhost + config = { + services.nginx = { + enable = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + recommendedProxySettings = true; + clientMaxBodySize = "10G"; + statusPage = true; # For metrics, should be accessible only from localhost + }; }; } diff --git a/configuration/nginx/logging.nix b/configuration/nginx/logging.nix index 0c6a955..e41bfae 100644 --- a/configuration/nginx/logging.nix +++ b/configuration/nginx/logging.nix @@ -1,4 +1,10 @@ -{ config, lib, ... }: +{ + flake-inputs, + pkgs, + config, + lib, + ... +}: let hostNames = lib.attrNames config.services.nginx.virtualHosts; logPath = name: "/var/log/nginx/${name}/access.log"; @@ -80,5 +86,55 @@ in }; }; }; + + serviceTests = + let + testHostConfig = + { config, ... }: + { + imports = [ + ./. + ../../modules/serviceTests/mocks.nix + ]; + + networking.firewall.allowedTCPPorts = [ 80 ]; + + services.nginx = { + domain = "testHost"; + virtualHosts."${config.services.nginx.domain}".locations."/".return = "200 ok"; + }; + }; + in + { + nginxMetricsWork = pkgs.testers.runNixOSTest { + name = "nginx-metrics-work"; + node.specialArgs = { inherit flake-inputs; }; + + nodes = { + testHost = testHostConfig; + + client = + { pkgs, ... }: + { + environment.systemPackages = [ pkgs.curl ]; + }; + }; + + testScript = '' + import time + + start_all() + + testHost.wait_for_unit("nginx.service") + client.succeed("curl --max-time 10 http://testHost") + + # Wait a bit for the prometheus exporter to scrape our logs + time.sleep(5) + + res = testHost.succeed("curl localhost:${builtins.toString config.services.prometheus.exporters.nginxlog.port}/metrics") + assert 'nginxlog_http_response_count_total{method="GET",status="200",vhost="testHost"} 1' in res, res + ''; + }; + }; }; } diff --git a/configuration/nginx/ssl.nix b/configuration/nginx/ssl.nix index 7abc38e..dc2b999 100644 --- a/configuration/nginx/ssl.nix +++ b/configuration/nginx/ssl.nix @@ -1,4 +1,5 @@ { + flake-inputs, pkgs, config, lib, @@ -69,5 +70,72 @@ "porkbun/api-key".owner = "acme"; "porkbun/secret-api-key".owner = "acme"; }; + + serviceTests = + let + testHostConfig = + { config, ... }: + { + imports = [ + ./. + ../../modules/serviceTests/mocks.nix + ]; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + security.acme.certs."tlater.net".extraDomainNames = [ config.services.nginx.domain ]; + + services.nginx = { + domain = "testHost"; + + virtualHosts."${config.services.nginx.domain}" = { + useACMEHost = "tlater.net"; + forceSSL = true; + enableHSTS = true; + locations."/".return = "200 ok"; + }; + }; + }; + in + { + hstsIsSet = pkgs.testers.runNixOSTest { + name = "hsts-is-set"; + + node.specialArgs = { inherit flake-inputs; }; + nodes = { + testHost = testHostConfig; + + client = + { pkgs, ... }: + { + environment.systemPackages = [ pkgs.curl ]; + }; + }; + + testScript = '' + start_all() + + testHost.wait_for_unit("nginx.service") + testHost.copy_from_vm("/var/lib/acme/tlater.net/", "certs") + client.copy_from_host(f"{testHost.out_dir}/certs", "/certs") + + client.succeed("curl --max-time 10 http://testHost") + res = client.succeed(" ".join([ + "curl", + "--show-error", + "--silent", + "--dump-header -", + "--cacert /certs/tlater.net/fullchain.pem", + "https://testHost", + "-o /dev/null" + ])) + + assert "strict-transport-security: max-age=15552000; includeSubDomains" in res + ''; + }; + }; }; } diff --git a/modules/default.nix b/modules/default.nix index 9483c66..1bf5314 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1 +1,6 @@ -{ imports = [ ./crowdsec ]; } +{ + imports = [ + ./crowdsec + ./serviceTests/stub.nix + ]; +} diff --git a/modules/serviceTests/mocks.nix b/modules/serviceTests/mocks.nix new file mode 100644 index 0000000..f864253 --- /dev/null +++ b/modules/serviceTests/mocks.nix @@ -0,0 +1,27 @@ +/** + Module containing mock definitions for service test runners. +*/ +{ flake-inputs, lib, ... }: +{ + imports = [ + flake-inputs.sops-nix.nixosModules.sops + ../. + ../../configuration/services/backups.nix + ]; + + sops.defaultSopsFile = ../../keys/staging.yaml; + environment.etc."staging.key" = { + mode = "0400"; + source = ../../keys/hosts/staging.key; + }; + services.openssh = { + enable = true; + hostKeys = lib.mkForce [ + { + type = "rsa"; + bits = 4096; + path = "/etc/staging.key"; + } + ]; + }; +} diff --git a/modules/serviceTests/stub.nix b/modules/serviceTests/stub.nix new file mode 100644 index 0000000..d4a4b78 --- /dev/null +++ b/modules/serviceTests/stub.nix @@ -0,0 +1,20 @@ +/** + Module to make writing service-specific tests easy. +*/ +{ lib, ... }: +let + inherit (lib) mkOption types; +in +{ + options = { + serviceTests = mkOption { + type = types.attrsOf types.package; + + description = '' + NixOS tests to run. + ''; + + default = { }; + }; + }; +} From d79bffe369d070138ab169c84376917f5fc8c81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:17:43 +0800 Subject: [PATCH 02/10] refactor(firewall): Make services responsible for opening ports --- configuration/default.nix | 40 +--------------------- configuration/services/conduit/default.nix | 30 ++++++++++++++++ configuration/services/foundryvtt.nix | 5 +++ configuration/services/gitea.nix | 5 +++ configuration/services/immich.nix | 5 +++ configuration/services/metrics/grafana.nix | 5 +++ configuration/services/nextcloud.nix | 5 +++ configuration/services/starbound.nix | 2 ++ configuration/services/webserver.nix | 5 +++ 9 files changed, 63 insertions(+), 39 deletions(-) diff --git a/configuration/default.nix b/configuration/default.nix index 6f73f54..08b63a1 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,9 +1,4 @@ -{ - config, - modulesPath, - flake-inputs, - ... -}: +{ modulesPath, flake-inputs, ... }: { imports = [ flake-inputs.disko.nixosModules.disko @@ -49,39 +44,6 @@ networking = { usePredictableInterfaceNames = false; useDHCP = false; - - firewall = { - allowedTCPPorts = [ - # http - 80 - 443 - # ssh - 2222 - # matrix - 8448 - # starbound - 21025 - - config.services.coturn.listening-port - config.services.coturn.tls-listening-port - config.services.coturn.alt-listening-port - config.services.coturn.alt-tls-listening-port - ]; - - allowedUDPPorts = [ - config.services.coturn.listening-port - config.services.coturn.tls-listening-port - config.services.coturn.alt-listening-port - config.services.coturn.alt-tls-listening-port - ]; - - allowedUDPPortRanges = [ - { - from = config.services.coturn.min-port; - to = config.services.coturn.max-port; - } - ]; - }; }; systemd.network.enable = true; diff --git a/configuration/services/conduit/default.nix b/configuration/services/conduit/default.nix index 6e01e81..b6f8f27 100644 --- a/configuration/services/conduit/default.nix +++ b/configuration/services/conduit/default.nix @@ -17,6 +17,36 @@ in ./matrix-hookshot.nix ]; + networking.firewall = { + allowedTCPPorts = [ + # These are for "normal" clients + 80 + 443 + + # Federation happens on 8448 + 8448 + + config.services.coturn.listening-port + config.services.coturn.tls-listening-port + config.services.coturn.alt-listening-port + config.services.coturn.alt-tls-listening-port + ]; + + allowedUDPPorts = [ + config.services.coturn.listening-port + config.services.coturn.tls-listening-port + config.services.coturn.alt-listening-port + config.services.coturn.alt-tls-listening-port + ]; + + allowedUDPPortRanges = [ + { + from = config.services.coturn.min-port; + to = config.services.coturn.max-port; + } + ]; + }; + services = { matrix-conduit = { enable = true; diff --git a/configuration/services/foundryvtt.nix b/configuration/services/foundryvtt.nix index 6c475a3..5c8a21f 100644 --- a/configuration/services/foundryvtt.nix +++ b/configuration/services/foundryvtt.nix @@ -11,6 +11,11 @@ in { imports = [ flake-inputs.foundryvtt.nixosModules.foundryvtt ]; + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { foundryvtt = { enable = true; diff --git a/configuration/services/gitea.nix b/configuration/services/gitea.nix index 613d30c..b4dd719 100644 --- a/configuration/services/gitea.nix +++ b/configuration/services/gitea.nix @@ -8,6 +8,11 @@ let domain = "gitea.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { forgejo = { enable = true; diff --git a/configuration/services/immich.nix b/configuration/services/immich.nix index 516ea3e..39673d0 100644 --- a/configuration/services/immich.nix +++ b/configuration/services/immich.nix @@ -8,6 +8,11 @@ let hostName = "immich.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { immich = { enable = true; diff --git a/configuration/services/metrics/grafana.nix b/configuration/services/metrics/grafana.nix index f4b6956..765a364 100644 --- a/configuration/services/metrics/grafana.nix +++ b/configuration/services/metrics/grafana.nix @@ -3,6 +3,11 @@ let domain = "metrics.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services.grafana = { enable = true; settings = { diff --git a/configuration/services/nextcloud.nix b/configuration/services/nextcloud.nix index ef2a6ac..77cfa4c 100644 --- a/configuration/services/nextcloud.nix +++ b/configuration/services/nextcloud.nix @@ -9,6 +9,11 @@ let hostName = "nextcloud.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { nextcloud = { inherit hostName; diff --git a/configuration/services/starbound.nix b/configuration/services/starbound.nix index a667b57..6b97471 100644 --- a/configuration/services/starbound.nix +++ b/configuration/services/starbound.nix @@ -8,6 +8,8 @@ let inherit (lib) concatStringsSep; in { + networking.firewall.allowedTCPPorts = [ 21025 ]; + # Sadly, steam-run requires some X libs environment.noXlibs = false; diff --git a/configuration/services/webserver.nix b/configuration/services/webserver.nix index 864f6c0..8f08e4f 100644 --- a/configuration/services/webserver.nix +++ b/configuration/services/webserver.nix @@ -3,6 +3,11 @@ let inherit (config.services.nginx) domain; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services.tlaternet-webserver = { enable = true; listen = { From 568962b57f4bcaee4cbbe2922476115dbe11a5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:22:32 +0800 Subject: [PATCH 03/10] chore: Disable hack for Minecraft optimization on VPS --- configuration/default.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/configuration/default.nix b/configuration/default.nix index 08b63a1..a020401 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -34,13 +34,6 @@ settings.trusted-users = [ "@wheel" ]; }; - # Optimization for minecraft servers, see: - # https://bugs.mojang.com/browse/MC-183518 - boot.kernelParams = [ - "highres=off" - "nohz=off" - ]; - networking = { usePredictableInterfaceNames = false; useDHCP = false; From fc9f53aafc479c83b36587adc5ecea5c4e54b92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:24:04 +0800 Subject: [PATCH 04/10] fix: Make the default package disabling actually work --- configuration/default.nix | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/configuration/default.nix b/configuration/default.nix index a020401..7e67c62 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,4 +1,9 @@ -{ modulesPath, flake-inputs, ... }: +{ + lib, + modulesPath, + flake-inputs, + ... +}: { imports = [ flake-inputs.disko.nixosModules.disko @@ -79,7 +84,7 @@ sops.defaultSopsFile = ../keys/production.yaml; # Remove some unneeded packages - environment.defaultPackages = [ ]; + environment.defaultPackages = lib.mkForce [ ]; system.stateVersion = "20.09"; } From 7233480d5ac057593d1b8e2b7f97d46eae06120b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:37:13 +0800 Subject: [PATCH 05/10] refactor: Move service imports into a `default.nix` --- configuration/default.nix | 18 ++---------------- configuration/services/default.nix | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 configuration/services/default.nix diff --git a/configuration/default.nix b/configuration/default.nix index 7e67c62..464f7ed 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -9,25 +9,11 @@ flake-inputs.disko.nixosModules.disko flake-inputs.sops-nix.nixosModules.sops flake-inputs.tlaternet-webserver.nixosModules.default - "${modulesPath}/profiles/minimal.nix" - ../modules - ./services/backups.nix - ./services/battery-manager.nix - ./services/conduit - ./services/crowdsec.nix - ./services/foundryvtt.nix - ./services/gitea.nix - ./services/immich.nix - ./services/metrics - ./services/minecraft.nix - ./services/nextcloud.nix - ./services/webserver.nix - ./services/wireguard.nix - # ./services/starbound.nix -- Not currently used - ./services/postgres.nix + ../modules ./nginx + ./services ]; nix = { diff --git a/configuration/services/default.nix b/configuration/services/default.nix new file mode 100644 index 0000000..adc4482 --- /dev/null +++ b/configuration/services/default.nix @@ -0,0 +1,18 @@ +{ + imports = [ + ./backups.nix + ./battery-manager.nix + ./conduit + ./crowdsec.nix + ./foundryvtt.nix + ./gitea.nix + ./immich.nix + ./metrics + ./minecraft.nix + ./nextcloud.nix + ./postgres.nix + # ./starbound.nix -- Not currently used + ./webserver.nix + ./wireguard.nix + ]; +} From c30e0c770a76e7165dcbae881f7c5f8fa0d3f791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Nov 2025 05:20:09 +0800 Subject: [PATCH 06/10] test(nginx): Add simple tests to assert nginx features work --- checks/default.nix | 2 + configuration/default.nix | 2 +- configuration/nginx/logging.nix | 58 +++++++++++++++++++++++++++- configuration/nginx/ssl.nix | 68 +++++++++++++++++++++++++++++++++ modules/default.nix | 7 +++- modules/serviceTests/mocks.nix | 27 +++++++++++++ modules/serviceTests/stub.nix | 20 ++++++++++ 7 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 modules/serviceTests/mocks.nix create mode 100644 modules/serviceTests/stub.nix diff --git a/checks/default.nix b/checks/default.nix index 674b19d..737313d 100644 --- a/checks/default.nix +++ b/checks/default.nix @@ -6,6 +6,8 @@ let in { x86_64-linux = lib.mergeAttrsList [ + flake-inputs.self.nixosConfigurations.hetzner-1.config.serviceTests + { nix = checkLib.mkLint { name = "nix-lints"; diff --git a/configuration/default.nix b/configuration/default.nix index 9881db2..6f73f54 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -11,7 +11,7 @@ flake-inputs.tlaternet-webserver.nixosModules.default "${modulesPath}/profiles/minimal.nix" - (import ../modules) + ../modules ./services/backups.nix ./services/battery-manager.nix diff --git a/configuration/nginx/logging.nix b/configuration/nginx/logging.nix index 0c6a955..e41bfae 100644 --- a/configuration/nginx/logging.nix +++ b/configuration/nginx/logging.nix @@ -1,4 +1,10 @@ -{ config, lib, ... }: +{ + flake-inputs, + pkgs, + config, + lib, + ... +}: let hostNames = lib.attrNames config.services.nginx.virtualHosts; logPath = name: "/var/log/nginx/${name}/access.log"; @@ -80,5 +86,55 @@ in }; }; }; + + serviceTests = + let + testHostConfig = + { config, ... }: + { + imports = [ + ./. + ../../modules/serviceTests/mocks.nix + ]; + + networking.firewall.allowedTCPPorts = [ 80 ]; + + services.nginx = { + domain = "testHost"; + virtualHosts."${config.services.nginx.domain}".locations."/".return = "200 ok"; + }; + }; + in + { + nginxMetricsWork = pkgs.testers.runNixOSTest { + name = "nginx-metrics-work"; + node.specialArgs = { inherit flake-inputs; }; + + nodes = { + testHost = testHostConfig; + + client = + { pkgs, ... }: + { + environment.systemPackages = [ pkgs.curl ]; + }; + }; + + testScript = '' + import time + + start_all() + + testHost.wait_for_unit("nginx.service") + client.succeed("curl --max-time 10 http://testHost") + + # Wait a bit for the prometheus exporter to scrape our logs + time.sleep(5) + + res = testHost.succeed("curl localhost:${builtins.toString config.services.prometheus.exporters.nginxlog.port}/metrics") + assert 'nginxlog_http_response_count_total{method="GET",status="200",vhost="testHost"} 1' in res, res + ''; + }; + }; }; } diff --git a/configuration/nginx/ssl.nix b/configuration/nginx/ssl.nix index 7abc38e..dc2b999 100644 --- a/configuration/nginx/ssl.nix +++ b/configuration/nginx/ssl.nix @@ -1,4 +1,5 @@ { + flake-inputs, pkgs, config, lib, @@ -69,5 +70,72 @@ "porkbun/api-key".owner = "acme"; "porkbun/secret-api-key".owner = "acme"; }; + + serviceTests = + let + testHostConfig = + { config, ... }: + { + imports = [ + ./. + ../../modules/serviceTests/mocks.nix + ]; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + security.acme.certs."tlater.net".extraDomainNames = [ config.services.nginx.domain ]; + + services.nginx = { + domain = "testHost"; + + virtualHosts."${config.services.nginx.domain}" = { + useACMEHost = "tlater.net"; + forceSSL = true; + enableHSTS = true; + locations."/".return = "200 ok"; + }; + }; + }; + in + { + hstsIsSet = pkgs.testers.runNixOSTest { + name = "hsts-is-set"; + + node.specialArgs = { inherit flake-inputs; }; + nodes = { + testHost = testHostConfig; + + client = + { pkgs, ... }: + { + environment.systemPackages = [ pkgs.curl ]; + }; + }; + + testScript = '' + start_all() + + testHost.wait_for_unit("nginx.service") + testHost.copy_from_vm("/var/lib/acme/tlater.net/", "certs") + client.copy_from_host(f"{testHost.out_dir}/certs", "/certs") + + client.succeed("curl --max-time 10 http://testHost") + res = client.succeed(" ".join([ + "curl", + "--show-error", + "--silent", + "--dump-header -", + "--cacert /certs/tlater.net/fullchain.pem", + "https://testHost", + "-o /dev/null" + ])) + + assert "strict-transport-security: max-age=15552000; includeSubDomains" in res + ''; + }; + }; }; } diff --git a/modules/default.nix b/modules/default.nix index 9483c66..1bf5314 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1 +1,6 @@ -{ imports = [ ./crowdsec ]; } +{ + imports = [ + ./crowdsec + ./serviceTests/stub.nix + ]; +} diff --git a/modules/serviceTests/mocks.nix b/modules/serviceTests/mocks.nix new file mode 100644 index 0000000..f864253 --- /dev/null +++ b/modules/serviceTests/mocks.nix @@ -0,0 +1,27 @@ +/** + Module containing mock definitions for service test runners. +*/ +{ flake-inputs, lib, ... }: +{ + imports = [ + flake-inputs.sops-nix.nixosModules.sops + ../. + ../../configuration/services/backups.nix + ]; + + sops.defaultSopsFile = ../../keys/staging.yaml; + environment.etc."staging.key" = { + mode = "0400"; + source = ../../keys/hosts/staging.key; + }; + services.openssh = { + enable = true; + hostKeys = lib.mkForce [ + { + type = "rsa"; + bits = 4096; + path = "/etc/staging.key"; + } + ]; + }; +} diff --git a/modules/serviceTests/stub.nix b/modules/serviceTests/stub.nix new file mode 100644 index 0000000..d4a4b78 --- /dev/null +++ b/modules/serviceTests/stub.nix @@ -0,0 +1,20 @@ +/** + Module to make writing service-specific tests easy. +*/ +{ lib, ... }: +let + inherit (lib) mkOption types; +in +{ + options = { + serviceTests = mkOption { + type = types.attrsOf types.package; + + description = '' + NixOS tests to run. + ''; + + default = { }; + }; + }; +} From 34e19034719f2b7e6bde35925e8f8d301a81afed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:17:43 +0800 Subject: [PATCH 07/10] refactor(firewall): Make services responsible for opening ports --- configuration/default.nix | 40 +--------------------- configuration/services/conduit/default.nix | 30 ++++++++++++++++ configuration/services/foundryvtt.nix | 5 +++ configuration/services/gitea.nix | 5 +++ configuration/services/immich.nix | 5 +++ configuration/services/metrics/grafana.nix | 5 +++ configuration/services/nextcloud.nix | 5 +++ configuration/services/starbound.nix | 2 ++ configuration/services/webserver.nix | 5 +++ 9 files changed, 63 insertions(+), 39 deletions(-) diff --git a/configuration/default.nix b/configuration/default.nix index 6f73f54..08b63a1 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,9 +1,4 @@ -{ - config, - modulesPath, - flake-inputs, - ... -}: +{ modulesPath, flake-inputs, ... }: { imports = [ flake-inputs.disko.nixosModules.disko @@ -49,39 +44,6 @@ networking = { usePredictableInterfaceNames = false; useDHCP = false; - - firewall = { - allowedTCPPorts = [ - # http - 80 - 443 - # ssh - 2222 - # matrix - 8448 - # starbound - 21025 - - config.services.coturn.listening-port - config.services.coturn.tls-listening-port - config.services.coturn.alt-listening-port - config.services.coturn.alt-tls-listening-port - ]; - - allowedUDPPorts = [ - config.services.coturn.listening-port - config.services.coturn.tls-listening-port - config.services.coturn.alt-listening-port - config.services.coturn.alt-tls-listening-port - ]; - - allowedUDPPortRanges = [ - { - from = config.services.coturn.min-port; - to = config.services.coturn.max-port; - } - ]; - }; }; systemd.network.enable = true; diff --git a/configuration/services/conduit/default.nix b/configuration/services/conduit/default.nix index 6e01e81..b6f8f27 100644 --- a/configuration/services/conduit/default.nix +++ b/configuration/services/conduit/default.nix @@ -17,6 +17,36 @@ in ./matrix-hookshot.nix ]; + networking.firewall = { + allowedTCPPorts = [ + # These are for "normal" clients + 80 + 443 + + # Federation happens on 8448 + 8448 + + config.services.coturn.listening-port + config.services.coturn.tls-listening-port + config.services.coturn.alt-listening-port + config.services.coturn.alt-tls-listening-port + ]; + + allowedUDPPorts = [ + config.services.coturn.listening-port + config.services.coturn.tls-listening-port + config.services.coturn.alt-listening-port + config.services.coturn.alt-tls-listening-port + ]; + + allowedUDPPortRanges = [ + { + from = config.services.coturn.min-port; + to = config.services.coturn.max-port; + } + ]; + }; + services = { matrix-conduit = { enable = true; diff --git a/configuration/services/foundryvtt.nix b/configuration/services/foundryvtt.nix index 6c475a3..5c8a21f 100644 --- a/configuration/services/foundryvtt.nix +++ b/configuration/services/foundryvtt.nix @@ -11,6 +11,11 @@ in { imports = [ flake-inputs.foundryvtt.nixosModules.foundryvtt ]; + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { foundryvtt = { enable = true; diff --git a/configuration/services/gitea.nix b/configuration/services/gitea.nix index 613d30c..b4dd719 100644 --- a/configuration/services/gitea.nix +++ b/configuration/services/gitea.nix @@ -8,6 +8,11 @@ let domain = "gitea.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { forgejo = { enable = true; diff --git a/configuration/services/immich.nix b/configuration/services/immich.nix index 516ea3e..39673d0 100644 --- a/configuration/services/immich.nix +++ b/configuration/services/immich.nix @@ -8,6 +8,11 @@ let hostName = "immich.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { immich = { enable = true; diff --git a/configuration/services/metrics/grafana.nix b/configuration/services/metrics/grafana.nix index f4b6956..765a364 100644 --- a/configuration/services/metrics/grafana.nix +++ b/configuration/services/metrics/grafana.nix @@ -3,6 +3,11 @@ let domain = "metrics.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services.grafana = { enable = true; settings = { diff --git a/configuration/services/nextcloud.nix b/configuration/services/nextcloud.nix index ef2a6ac..77cfa4c 100644 --- a/configuration/services/nextcloud.nix +++ b/configuration/services/nextcloud.nix @@ -9,6 +9,11 @@ let hostName = "nextcloud.${config.services.nginx.domain}"; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services = { nextcloud = { inherit hostName; diff --git a/configuration/services/starbound.nix b/configuration/services/starbound.nix index a667b57..6b97471 100644 --- a/configuration/services/starbound.nix +++ b/configuration/services/starbound.nix @@ -8,6 +8,8 @@ let inherit (lib) concatStringsSep; in { + networking.firewall.allowedTCPPorts = [ 21025 ]; + # Sadly, steam-run requires some X libs environment.noXlibs = false; diff --git a/configuration/services/webserver.nix b/configuration/services/webserver.nix index 864f6c0..8f08e4f 100644 --- a/configuration/services/webserver.nix +++ b/configuration/services/webserver.nix @@ -3,6 +3,11 @@ let inherit (config.services.nginx) domain; in { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + services.tlaternet-webserver = { enable = true; listen = { From 7f0cf674137039b8e2e8fdfa716b2066ad9d6a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:22:32 +0800 Subject: [PATCH 08/10] chore: Disable hack for Minecraft optimization on VPS --- configuration/default.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/configuration/default.nix b/configuration/default.nix index 08b63a1..a020401 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -34,13 +34,6 @@ settings.trusted-users = [ "@wheel" ]; }; - # Optimization for minecraft servers, see: - # https://bugs.mojang.com/browse/MC-183518 - boot.kernelParams = [ - "highres=off" - "nohz=off" - ]; - networking = { usePredictableInterfaceNames = false; useDHCP = false; From d5998094607baa08b78befa2c6a40d6da8063b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:24:04 +0800 Subject: [PATCH 09/10] fix: Make the default package disabling actually work --- configuration/default.nix | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/configuration/default.nix b/configuration/default.nix index a020401..7e67c62 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,4 +1,9 @@ -{ modulesPath, flake-inputs, ... }: +{ + lib, + modulesPath, + flake-inputs, + ... +}: { imports = [ flake-inputs.disko.nixosModules.disko @@ -79,7 +84,7 @@ sops.defaultSopsFile = ../keys/production.yaml; # Remove some unneeded packages - environment.defaultPackages = [ ]; + environment.defaultPackages = lib.mkForce [ ]; system.stateVersion = "20.09"; } From d5616a2477fd8bc773e91f03f0051014ac17dfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 20 Nov 2025 00:37:13 +0800 Subject: [PATCH 10/10] refactor: Move service imports into a `default.nix` --- configuration/default.nix | 18 ++---------------- configuration/services/default.nix | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 configuration/services/default.nix diff --git a/configuration/default.nix b/configuration/default.nix index 7e67c62..464f7ed 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -9,25 +9,11 @@ flake-inputs.disko.nixosModules.disko flake-inputs.sops-nix.nixosModules.sops flake-inputs.tlaternet-webserver.nixosModules.default - "${modulesPath}/profiles/minimal.nix" - ../modules - ./services/backups.nix - ./services/battery-manager.nix - ./services/conduit - ./services/crowdsec.nix - ./services/foundryvtt.nix - ./services/gitea.nix - ./services/immich.nix - ./services/metrics - ./services/minecraft.nix - ./services/nextcloud.nix - ./services/webserver.nix - ./services/wireguard.nix - # ./services/starbound.nix -- Not currently used - ./services/postgres.nix + ../modules ./nginx + ./services ]; nix = { diff --git a/configuration/services/default.nix b/configuration/services/default.nix new file mode 100644 index 0000000..adc4482 --- /dev/null +++ b/configuration/services/default.nix @@ -0,0 +1,18 @@ +{ + imports = [ + ./backups.nix + ./battery-manager.nix + ./conduit + ./crowdsec.nix + ./foundryvtt.nix + ./gitea.nix + ./immich.nix + ./metrics + ./minecraft.nix + ./nextcloud.nix + ./postgres.nix + # ./starbound.nix -- Not currently used + ./webserver.nix + ./wireguard.nix + ]; +}