Files
server-config/tests/fail2ban-gitea.nix
Simon Gardling da6b4d1915 tests: fix all fail2ban NixOS VM tests
- Add explicit iptables banaction in security.nix for test compatibility
- Force IPv4 in all curl requests to prevent IPv4/IPv6 mismatch issues
- Fix caddy test: use basic_auth directive (not basicauth)
- Override service ports in tests to match direct connections (not via Caddy)
- Vaultwarden: override ROCKET_ADDRESS and ROCKET_LOG for external access
- Immich: increase VM memory to 4GB for stability
- Jellyfin: create placeholder log file and reload fail2ban after startup
- Add tests.nix entries for all 6 fail2ban tests

All tests now pass: ssh, caddy, gitea, vaultwarden, immich, jellyfin
2026-01-20 18:41:01 -05:00

115 lines
3.0 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
testServiceConfigs = {
zpool_ssds = "";
gitea = {
dir = "/var/lib/gitea";
domain = "git.test.local";
};
postgres = {
socket = "/run/postgresql";
};
ports = {
gitea = 3000;
};
};
testLib = lib.extend (
final: prev: {
serviceMountWithZpool = serviceName: zpool: dirs: { ... }: { };
}
);
giteaModule =
{ config, pkgs, ... }:
{
imports = [
(import ../services/gitea.nix {
inherit config pkgs;
lib = testLib;
service_configs = testServiceConfigs;
})
];
};
in
pkgs.testers.runNixOSTest {
name = "fail2ban-gitea";
nodes = {
server =
{ config, lib, pkgs, ... }:
{
imports = [
../modules/security.nix
giteaModule
];
# Enable postgres for gitea
services.postgresql.enable = true;
# Disable ZFS mount dependency
systemd.services."gitea-mounts".enable = lib.mkForce false;
systemd.services.gitea = {
wants = lib.mkForce [ ];
after = lib.mkForce [ "postgresql.service" ];
requires = lib.mkForce [ ];
};
# Override for faster testing and correct port
services.fail2ban.jails.gitea.settings = {
maxretry = lib.mkForce 3;
# In test, we connect directly to Gitea port, not via Caddy
port = lib.mkForce "3000";
};
networking.firewall.allowedTCPPorts = [ 3000 ];
};
client = {
environment.systemPackages = [ pkgs.curl ];
};
};
testScript = ''
import time
import re
start_all()
server.wait_for_unit("postgresql.service")
server.wait_for_unit("gitea.service")
server.wait_for_unit("fail2ban.service")
server.wait_for_open_port(3000)
time.sleep(3)
with subtest("Verify gitea jail is active"):
status = server.succeed("fail2ban-client status")
assert "gitea" in status, f"gitea jail not found in: {status}"
with subtest("Generate failed login attempts"):
# Use -4 to force IPv4 for consistent IP tracking
for i in range(4):
client.execute(
"curl -4 -s -X POST http://server:3000/user/login -d 'user_name=baduser&password=badpass' || true"
)
time.sleep(0.5)
with subtest("Verify IP is banned"):
time.sleep(3)
status = server.succeed("fail2ban-client status gitea")
print(f"gitea jail status: {status}")
# Check that at least 1 IP is banned
match = re.search(r"Currently banned:\s*(\d+)", status)
assert match and int(match.group(1)) >= 1, f"Expected at least 1 banned IP, got: {status}"
with subtest("Verify banned client cannot connect"):
# Use -4 to test with same IP that was banned
exit_code = client.execute("curl -4 -s --max-time 3 http://server:3000/ 2>&1")[0]
assert exit_code != 0, "Connection should be blocked"
'';
}