- VM test boots a VM and verifies PostgreSQL, conduwuit, dnsmasq, nginx - Shellcheck runs on all shell scripts (errors and warnings) - Fix unused variables in sanitize-files.sh - Use initialHashedPassword for root in VM config 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
149 lines
4.5 KiB
Nix
149 lines
4.5 KiB
Nix
# 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!")
|
|
'';
|
|
}
|