# NixOS VM integration test for ops-jrz1 # Boots a VM and verifies core services start correctly # # Run with: nix flake check (as part of checks) # Or standalone: nix build .#checks.x86_64-linux.vm-integration { pkgs, pkgs-unstable, opencode }: pkgs.nixosTest { name = "ops-jrz1-integration"; # Type checker doesn't know about injected node variables skipTypeCheck = true; # Linter (pyflakes) can't see dynamically injected node names like 'server' skipLint = true; nodes.server = { lib, ... }: { # Disable built-in NixOS maubot module to use our custom version disabledModules = [ "services/matrix/maubot.nix" ]; imports = [ ../modules/matrix-continuwuity.nix ../modules/mautrix-slack.nix ../modules/mautrix-whatsapp.nix ../modules/mautrix-gmessages.nix ../modules/maubot.nix ../modules/dev-services.nix ../modules/security/fail2ban.nix ../modules/security/ssh-hardening.nix ]; # Provide pkgs-unstable to modules that need it _module.args = { inherit pkgs-unstable opencode; }; # VM-specific settings networking.hostName = "ops-jrz1-vm"; # Local DNS resolver for conduwuit (VM sandbox has no external network) services.dnsmasq = { enable = true; settings = { # Resolve only specific test hostnames (more explicit than wildcard) address = [ "/matrix.example.org/127.0.0.1" "/example.org/127.0.0.1" ]; no-resolv = true; no-hosts = false; }; }; networking.nameservers = lib.mkForce [ "127.0.0.1" ]; # Enable Matrix homeserver services.matrix-homeserver = { enable = true; domain = "matrix.example.org"; port = 8008; enableRegistration = false; # Disabled - conduwuit refuses open registration enableFederation = false; }; # Enable Slack bridge services.mautrix-slack = { enable = true; matrix = { homeserverUrl = "http://127.0.0.1:8008"; serverName = "matrix.example.org"; }; bridge.permissions = { "matrix.example.org" = "user"; "@admin:matrix.example.org" = "admin"; }; }; # PostgreSQL for bridge databases services.postgresql = { enable = true; ensureDatabases = [ "mautrix_slack" ]; ensureUsers = [{ name = "mautrix_slack"; ensureDBOwnership = true; }]; }; # Configure nginx directly for VM testing (plain HTTP, no ACME) services.nginx = { enable = true; recommendedProxySettings = true; virtualHosts."matrix.example.org" = { locations."/_matrix" = { proxyPass = "http://127.0.0.1:8008"; proxyWebsockets = true; }; locations."/.well-known/matrix" = { proxyPass = "http://127.0.0.1:8008"; }; }; }; # VM testing settings services.openssh.settings.PasswordAuthentication = lib.mkForce true; users.users.root.initialHashedPassword = ""; # Empty password for VM test (silences warning) networking.firewall = { enable = true; allowedTCPPorts = [ 22 80 443 8008 3000 ]; }; # Required for VM virtualisation.memorySize = 2048; }; testScript = '' # NixOS test framework uses hostname (with hyphens->underscores) as Python variable machine = ops_jrz1_vm machine.start() machine.wait_for_unit("multi-user.target") # DNS must be up first (conduwuit needs it) machine.wait_for_unit("dnsmasq.service") # Test PostgreSQL machine.wait_for_unit("postgresql.service") machine.succeed("sudo -u postgres psql -c 'SELECT 1'") # Test Matrix homeserver (continuwuity/conduwuit) machine.wait_for_unit("continuwuity.service", timeout=60) machine.wait_for_open_port(8008) machine.succeed("curl -sf http://localhost:8008/_matrix/client/versions | grep -q versions") # Verify Matrix API returns valid JSON with versions array machine.succeed("curl -sf http://localhost:8008/_matrix/client/versions | grep -q 'v1.'") # Test nginx reverse proxy (plain HTTP) machine.wait_for_unit("nginx.service") machine.wait_for_open_port(80) # Test nginx proxies to Matrix homeserver correctly machine.succeed("curl -sf http://matrix.example.org/_matrix/client/versions | grep -q versions") # Verify nginx adds forwarding headers (X-Forwarded-For should be set) machine.succeed("curl -sf -H 'Host: matrix.example.org' http://127.0.0.1/_matrix/client/versions | grep -q versions") machine.log("All core services started successfully!") ''; }