Skip to content

Breakpoint Hook

The NixOS test driver can stop immediately when a test fails and leave the test environment available for inspection. This is controlled by the top-level enableDebugHook option from the test options reference in the NixOS manual.

This feature is most useful for failures that are hard to reproduce in interactive mode, especially flaky tests that only fail sometimes inside the sandboxed build.

How it Works

When enableDebugHook = true; is set, a failing test does not exit immediately. Instead, the driver pauses execution and prints instructions for attaching to the suspended test environment.

From there, you can:

  • connect to the test driver with telnet localhost 4444
  • connect to test machines over SSH via vsock when sshBackdoor.enable = true; is also enabled

Please also refer to the NixOS manual section about the debug hook.

Minimal Setup

test.nix
{
  name = "test";

  nodes.machine = { };

  sshBackdoor.enable = true;
  enableDebugHook = true;

  testScript = ''
    start_all()
    machine.succeed("false") # this will fail and trigger the breakpoint hook
  '';
}

To make SSH access via VSOCK available inside the sandbox, the test build must expose /dev/vhost-vsock:

nix build .#my-test --option sandbox-paths /dev/vhost-vsock
nix-build run-test.nix --option sandbox-paths /dev/vhost-vsock

Early in the build, the driver prints the SSH backdoor information, including the vsock addresses for the machines. For the first VM, that is typically vsock/3.

The output typically looks like this:

# ...
vm-test-run-test> SSH backdoor enabled, the machines can be accessed like this:
vm-test-run-test> Note: vsocks require systemd-ssh-proxy(1) to be enabled (default on NixOS 25.05 and newer).
vm-test-run-test>     machine1:  ssh -o User=root vsock/3
vm-test-run-test>     machine2:  ssh -o User=root vsock/4
# ...

Attaching After a Failure

After the failure, the test output includes an attach command for entering the sandbox shell. It typically looks like this:

vm-test-run-test> machine: must succeed: false
vm-test-run-test> !!! Traceback (most recent call last):
vm-test-run-test> !!!   File "<string>", line 13, in <module>
vm-test-run-test> !!!     machine.succeed("false")
vm-test-run-test> !!!
vm-test-run-test> !!! RequestedAssertionFailed: command `false` unexpectedly failed
vm-test-run-test> !!! Breakpoint reached, run 'sudo /nix/store/ksr4kryl9jl2rmgyhjw9bn2divr3s2d5-attach/bin/attach 3766386'

Once attached, you can connect to the VM with the generated SSH configuration:

ssh -F ./ssh_config root@vsock/3

You can also connect to the paused test driver with:

telnet 127.0.0.1 4444

That is especially useful when you want to inspect the current driver state or step through the script with pdb after an explicit debug.breakpoint().

sshBackdoor.enable is intended for debugging and provides unauthenticated access to the VMs.

The SSH backdoor is typically paired with the interactive driver, but it can also be used together with enableDebugHook for sandboxed failures.

Avoid relying on globalTimeout while using the breakpoint hook, because the timeout may terminate the paused test before you can inspect it.