test(nginx): Add simple tests to assert nginx features work

This commit is contained in:
Tristan Daniël Maat 2025-11-13 05:20:09 +08:00
parent 4e59582de2
commit f2ef91672b
Signed by: tlater
GPG key ID: 02E935006CF2E8E7
6 changed files with 176 additions and 2 deletions

View file

@ -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";

View file

@ -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
'';
};
};
};
}

View file

@ -1,4 +1,5 @@
{
flake-inputs,
pkgs,
config,
lib,
@ -69,5 +70,68 @@
"porkbun/api-key".owner = "acme";
"porkbun/secret-api-key".owner = "acme";
};
serviceTests =
let
testHostConfig =
{ config, ... }:
{
imports = [
./.
../../modules/serviceTests/mocks.nix
];
networking.firewall.allowedTCPPorts = [ 443 ];
security.acme.certs."tlater.net".extraDomainNames = [ config.services.nginx.domain ];
services.nginx = {
domain = "testHost";
virtualHosts."${config.services.nginx.domain}" = {
useACMEHost = "tlater.net";
onlySSL = true;
enableHSTS = true;
locations."/".return = "200 ok";
};
};
};
in
{
testNginxSSL = pkgs.testers.runNixOSTest {
name = "test-nginx-ssl";
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")
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
'';
};
};
};
}

View file

@ -1 +1,6 @@
{ imports = [ ./crowdsec ]; }
{
imports = [
./crowdsec
./serviceTests/stub.nix
];
}

View file

@ -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";
}
];
};
}

View file

@ -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 = { };
};
};
}