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/ssl.nix b/configuration/nginx/ssl.nix index 7abc38e..33941b6 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, ... }: + { + _module.args = { inherit flake-inputs; }; + imports = [ + ./. + ../../modules/serviceTests/mocks.nix + flake-inputs.sops-nix.nixosModules.sops + ]; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + security.acme.certs."tlater.net".extraDomainNames = [ "testHost" ]; + + 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 = "assert-hsts"; + 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..6d7be84 --- /dev/null +++ b/modules/serviceTests/mocks.nix @@ -0,0 +1,27 @@ +/** + Module containing mock definitions for service test runners. +*/ +{ lib, ... }: +{ + imports = [ + ../. + ../../configuration/services/backups.nix + ]; + # imports = [ flake-inputs.sops-nix.nixosModules.sops ]; + + 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 = { }; + }; + }; +}