Skip to content

Template: MicroVM

templates/microvm demonstrates Den’s extensibility: custom den.ctx and den.schema extensions for integrating other Nix libraries like MicroVM.nix.

This template shows two patterns for building MicroVMs with Den.

A standalone NixOS configuration that runs as MicroVM directly as an application.

Terminal window
nix run .#runnable-microvm

See MicroVM Docs on Package Runners

Guest MicroVMs declared on a host and managed together.

Terminal window
nixos-rebuild build --flake .#server

See MicroVM Docs on Declarative MicroVMs

Terminal window
mkdir my-nix && cd my-nix
nix flake init -t github:vic/den#microvm
nix flake update den
flake.nix
modules/
den.nix # Enable Den + hostname for all hosts
runnable-example.nix # Standalone NixOS MicroVM
microvm-runners.nix # Auto-expose runnable VMs as flake packages
guests-example.nix # Server host with declarative guest VMs
microvm-integration.nix # Schema extensions + context pipelines

Any runnable MicroVM with declaredRunner is auto-exposed as a flake package:

modules/microvm-runners.nix
flake.packages = {
x86_64-linux.runnable-microvm = <runner>;
};

microvm-integration.nix extends den.schema.host with MicroVM-specific options:

options.microvm.guests = lib.mkOption {
type = lib.types.listOf lib.types.raw;
description = "List of Den hosts to run as guest VMs";
};
options.microvm.sharedNixStore = lib.mkEnableOption "Auto share nix store";
modules/guests-example.nix
# Server host with guest VM
den.hosts.x86_64-linux.server.microvm.guests = [
den.hosts.x86_64-linux.guest-microvm
];
# Guest VM declaration (no top-level nixosConfiguration)
den.hosts.x86_64-linux.guest-microvm.intoAttr = [];
# Server config
den.aspects.server = {
nixos.microvm.host.startupTimeout = 300;
};
den.aspects.guest-microvm = {
# Den resolved and forwarded to `<host>.microvm.vms.guest-microvm.config`
nixos = { pkgs, ... }: {
environment.systemPackages = [ pkgs.cowsay ];
};
# Forwarded to `<host>.microvm.vms.guest-microvm`
microvm.autostart = true;
};

Two-stage pipeline for MicroVM host and guests:

# Stage 1: host → microvm-host (only if guests is non-empty)
ctx.host.into.microvm-host = { host }:
lib.optional (host.microvm.guests != []) { inherit host; };
# microvm-host provides Host configuration
ctx.microvm-host.provides.microvm-host = { host }: {
${host.class}.imports = [ host.microvm.hostModule ];
};
# Stage 2: microvm-host → microvm-guest
ctx.microvm-host.into.microvm-guest = { host }:
map (vm: { inherit host vm; }) host.microvm.guests;
# Guest configuration forwarded to host
ctx.microvm-host.provides.microvm-guest = { host, vm }: {
includes = [
# Auto-share nix store if enabled
sharedNixStore
# Den resolved NixOS module forwarded to <host>.nixos.microvm.vms.${vm.name}.config
(den.provides.forward { ... })
# Forward guest `microvm` class directly to <host>.nixos.microvm.vms.${vm.name}
(den.provides.forward { ... })
];
};
graph TD
    D1["server host"]
    D2["den.ctx.host<br/>normal pipeline"]
    D3["server nixos config"]
    D5["host.microvm.host<br/>loaded"]
    
    D6["guest-microvm host"]
    D7["den.ctx.host<br/>NORMAL PIPELINE"]
    D8["guest nixos config<br/>+ microvm class<br/>all Den features supported"]
    
    D9["forward to host:<br/>microvm.vms.guest-microvm.config"]
    D10["forward to host:<br/>microvm.vms.guest-microvm"]
    D11["server nixosConfiguration"]

    D1 -->|Den transforms to| D2
    D2 -->|microvm.guests != empty<br/>triggers microvm-host| D5
    D2 -->|produces| D3
    
    D6 -->|Uses normal Den pipeline<br/>den.ctx.host host=guest| D7
    D7 -->|produces| D8
    
    D8 -->|forward nixos| D9
    D8 -->|forward microvm| D10
    D3 --> D11
    D5 --> D11
    D9 --> D11
    D10 --> D11
FeatureProvided
Custom context pipelines
Schema extensions
Forward providers
Standalone runnable VMs
Host-guest architecture
Declarative MicroVM
Auto nix store sharing
Contribute Community Sponsor