{ config, lib, pkgs, inputs, ... }: let testServerName = "testserver"; # Create pkgs with nix-minecraft overlay and unfree packages allowed testPkgs = import inputs.nixpkgs { system = pkgs.stdenv.targetPlatform.system; config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ "minecraft-server" ]; overlays = [ inputs.nix-minecraft.overlay (import ../modules/overlays.nix) ]; }; testServiceConfigs = { zpool_ssds = ""; https = { domain = "test.local"; }; minecraft = { parent_dir = "/var/lib/minecraft"; server_name = testServerName; }; }; testLib = lib.extend ( final: prev: { serviceMountWithZpool = serviceName: zpool: dirs: { ... }: { }; } ); minecraftModule = { config, lib, ... }: { imports = [ (import ../services/minecraft.nix { inherit config inputs; pkgs = testPkgs; lib = testLib; service_configs = testServiceConfigs; }) ]; # Override nixpkgs config to prevent conflicts in test environment nixpkgs.config = lib.mkForce { allowUnfreePredicate = pkg: builtins.elem (testPkgs.lib.getName pkg) [ "minecraft-server" ]; }; # Disable whitelist import to avoid missing secrets file and reduce memory services.minecraft-servers.servers.${testServerName} = { whitelist = lib.mkForce { }; jvmOpts = lib.mkForce "-Xmx1G -Xms1G"; }; }; in testPkgs.testers.runNixOSTest { name = "fail2ban-minecraft"; nodes = { server = { config, lib, pkgs, ... }: { imports = [ ../modules/security.nix minecraftModule ]; # Disable ZFS mount dependency systemd.services."minecraft-server-${testServerName}-mounts".enable = lib.mkForce false; systemd.services."minecraft-server-${testServerName}" = { wants = lib.mkForce [ ]; after = lib.mkForce [ ]; requires = lib.mkForce [ ]; }; # Override for faster testing services.fail2ban.jails.minecraft.settings = { maxretry = lib.mkForce 3; findtime = lib.mkForce "5m"; bantime = lib.mkForce "10m"; }; # Create log directory and placeholder for fail2ban systemd.tmpfiles.rules = [ "d /var/lib/minecraft/${testServerName}/logs 0755 minecraft minecraft" "f /var/lib/minecraft/${testServerName}/logs/latest.log 0644 minecraft minecraft" ]; # Make fail2ban start after minecraft systemd.services.fail2ban = { wants = [ "minecraft-server-${testServerName}.service" ]; after = [ "minecraft-server-${testServerName}.service" ]; }; # Give minecraft server more resources virtualisation.diskSize = 4 * 1024; virtualisation.memorySize = 4 * 1024; }; client = { pkgs, ... }: { environment.systemPackages = [ (pkgs.python3.withPackages (ps: [ ps.mcstatus ])) ]; }; }; testScript = '' import time start_all() # Wait for minecraft server to fully start server.wait_for_unit("minecraft-server-${testServerName}.service", timeout=180) server.wait_for_unit("fail2ban.service") server.wait_for_open_port(25565, timeout=120) # Wait for server to be ready (shows "Done" in logs) server.wait_until_succeeds( "grep -q 'Done' /var/lib/minecraft/${testServerName}/logs/latest.log", timeout=120 ) time.sleep(2) # Reload fail2ban now that the real log file exists server.succeed("fail2ban-client reload minecraft") time.sleep(2) with subtest("Verify minecraft jail is active"): status = server.succeed("fail2ban-client status") print(f"fail2ban status:\n{status}") assert "minecraft" in status, f"minecraft jail not found in: {status}" with subtest("Verify jail configuration"): # Check jail status shows it's monitoring the log file status = server.succeed("fail2ban-client status minecraft") print(f"Jail status:\n{status}") assert "minecraft" in status, "minecraft jail not properly configured" with subtest("Check server logs"): logs = server.succeed("tail -20 /var/lib/minecraft/${testServerName}/logs/latest.log") print(f"Server logs:\n{logs}") with subtest("Test regex with fail2ban-regex"): # Test the filter regex against the log file result = server.execute("fail2ban-regex /var/lib/minecraft/${testServerName}/logs/latest.log /etc/fail2ban/filter.d/minecraft.local 2>&1") print(f"Regex test result:\n{result}") with subtest("Verify jail is functional"): # The jail should be running and monitoring - mcstatus won't trigger bans # since it only does status pings, not login attempts that would fail whitelist status = server.succeed("fail2ban-client status minecraft") print(f"Final jail status:\n{status}") # Verify the jail is running (has filter file loaded) assert "Filter" in status or "File list" in status or "Currently" in status, "Jail not properly running" ''; }