Operand

come place sense.

gram: pool

pool

Relaxing Nix process-pooling, based on microvm.nix. In progress.


Supply-side package exploits are a serious problem, causing coders to look again at local-machine process isolation, such as recommended and produced by the Qubes OS group for many years.

Here is one approach able to reproduce many of the functions of Qubes; ergonomic (by some measure), on-demand VMs, scoped to specific disc volumes or network schemas, managed using Nix flakes, running in parallel to any bare-metal operations.

Properly scoped, pool can be used to manage production processes also, and uses simple per-codebase flake.nix functions to compose a secure machine image for local or production use.

Dip in.

Using a NixOS machine as your base layer, clone this codebase to /pool.

Include pool modules in your /etc/nixos/flake.nix:

{ inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
pool = { url = "/pool"; inputs.nixpkgs.follows = "nixpkgs"; };
};
outputs = { microvm, pool, nixpkgs, ... }: let
arch = "x86_64-linux";
in {
nixosConfigurations.local = nixpkgs.lib.nixosSystem {
modules = [
# machine's primary outbound internet connection.
((pool.outputs.current arch).channel "wlan0")
sources.microvm.nixosModules.host
];
# ... remaining local config.
};
};
}

Splash around.

In each code base you'd like to isolate, include (and modify) this minimal flake.nix:

{ inputs = {
# nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
pool = { url = "/pool"; }; # inputs.nixpkgs.follows = "nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, pool, flake-utils }:
flake-utils.lib.eachDefaultSystem (arch: let
current = pool.outputs.current arch;
in {
packages.machine = (
current.condense "machine" "10.0.0.2" "enp0s4" {
users.users.root = current.role "root" {};
}).config.microvm.declaredRunner;
});
}

Rinse up.

sudo nix run .#machine

(network-patching requires super-user permissions)

  • You should see a machine spin up;
  • the login is root, no passcode required.
  • The normal shell is nushell.
  • Ensure DHCP assigned an IP addres, using ip a.
  • Close the machine, using shutdown now as a superuser.

Dry off.

Please recognize that there is a small issue in mapping network interfaces. You may need to keep an eye on the third argument to current.condense, the network interface such as "enp0s4"; this should mirror the label you see in ip a, as seen from inside the vm.

Example: users.users.

root only, no-pass:

{ users.users.root = role local "root" {}; }

root only, pass:

{ users.users.root = role local "root" { pass = "abcd1234"; }; }

normal user only, ssh login

{ users.users.access = role "access" { keys = [
"ssh-ed25519 AAAAC3NzaCetcetera/etceteraJZMfk3QPfQ foo@bar"
]; }; }

Clouds on the Horizon?

  • Properly (reliably) map network interfaces.
  • Include a Nebula mesh-VPN management module.