Introducing: no-headache.nix - Simple, Declarative Multi-VM Setups

Hello, Nix community!

I’m excited to share no-headache.nix with you:
Notably Opinionated yet Highly Extensible And Declarative Approach for Configuring Hundreds of Environments (using Nix)

Managing multiple local VMs for testing or development can be a headache - no-headache.nix aims to make it simple, fast, and declarative.
It’s perfect for projects that need:

  • Per-VM declarative configuration
  • Quick and easy VMs setup
  • Running multiple instances of the same configuration
  • Minimal mental overhead compared to complex virtualization tools or cloud infrastructure

All VMs are defined in a single configs.nix file, making it easy to configure, build, and launch.

The goal is to make configuring many local VMs easier, even for people new to the Nix ecosystem.
With just a few commands, you can install it and get your first VM network up and running.

Example: 4 VMs - 3 identical clients and 1 server.
They automatically connect via Tailscale, share a host directory, and run Python scripts after boot.

{ pkgs, customArgs, ... }:
let
  # Auth file has only tailscale auth key. Tailscale is optional.
  tsKeyFile = ../../secrets/tailscale.authkey;
  sharedDirectory = {
    debugSharedDir = {
      source = "/tmp/my-nixos-vms-shared/server-client";
      target = "/mnt/shared";
    };
  };
in
{
  # Config for the first VM type - a client
  client = {
    tailscaleAuthKeyFile = tsKeyFile;
    count = 3; # Simply change number of client instances!
    init.script = ''
      echo "Starting python client script..." &> ~/output.txt
      python ~/client.py &>> ~/output.txt
    '';
    copyToHome = {
      "client.py" = ./client.py;
    };
    nixos-config = {
      environment.systemPackages = with pkgs; [ python3 ];
      # Any other nixos options...
    };
    nixos-config-virt = {
      virtualisation.sharedDirectories = sharedDirectory;
      # Any other nixos virtualisation options...
    };
  };

  # Config for the second VM type - a server
  server = {
    tailscaleAuthKeyFile = tsKeyFile;
    init.script = ''
      echo "Starting python server script..." &> ~/output.txt
      python ~/server.py &>> ~/output.txt
    '';
    copyToHome = {
      "server.py" = ./server.py;
    };
    nixos-config = {
      environment.systemPackages = with pkgs; [ python3 ];
      networking.firewall.allowedTCPPorts = [ 5000 ];
      # Any other nixos options...
    };
    nixos-config-virt = {
      virtualisation.sharedDirectories = sharedDirectory;
      # Any other nixos virtualisation options...
    };
  };
}

Then, just run two commands to get your entire network up: nohead build and nohead runall.

I’d love to get your feedback.
Do you have similar use cases? Check out the GitHub repo for installation instructions, documentation, and examples:
https://github.com/JakovTomasic/no-headache.nix

3 Likes