From dc5069e9b2273659b62e911c4593dab6266927bb Mon Sep 17 00:00:00 2001 From: Jermeiah S Date: Thu, 10 Jul 2025 01:25:45 -0400 Subject: [PATCH] init --- .gitignore | 2 + configuration.nix | 71 +++++++++++++++++++++++++++++++++ flake.lock | 99 +++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 41 ++++++++++++++++++++ microvm.nix | 40 +++++++++++++++++++ scripts/run-vm.sh | 38 ++++++++++++++++++ vm-variant.nix | 32 +++++++++++++++ 7 files changed, 323 insertions(+) create mode 100644 .gitignore create mode 100644 configuration.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 microvm.nix create mode 100644 scripts/run-vm.sh create mode 100644 vm-variant.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..859059f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.img +*.qcow2 diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..9764f2d --- /dev/null +++ b/configuration.nix @@ -0,0 +1,71 @@ +{ + config, + lib, + pkgs, + ... +}: +let + indexHtml = pkgs.writeText "index.html" '' + hello mofo + ''; +in +{ + imports = [ + ./microvm.nix + ./vm-variant.nix + ]; + networking = { + firewall.enable = false; + useDHCP = lib.mkForce true; + hostName = "demo"; + }; + services.avahi = { + enable = true; + nssmdns = true; + publish = { + enable = true; + addresses = true; + workstation = true; + }; + }; + # boot = { + # # loader.grub.device = "nodev"; + # kernelParams = [ "console=ttyS0" ]; + # }; + + users.users = { + root = { + password = ""; + }; + }; + + # Optional: Make sure DNS is configured + networking = { + nameservers = [ + "9.9.9.9" + ]; + # Enable networking + # networkmanager.enable = true; + }; + nix = { + settings.experimental-features = [ + "nix-command" + "flakes" + ]; + }; + services.nginx = { + enable = true; + virtualHosts."localhost" = { + root = "${pkgs.runCommand "nginx-root" { } '' + mkdir -p $out + cp ${indexHtml} $out/index.html + ''}"; + locations."/" = { + index = "index.html"; + }; + }; + }; + + # users.mutableUsers = false; + system.stateVersion = "25.05"; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..70a6b6a --- /dev/null +++ b/flake.lock @@ -0,0 +1,99 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "microvm": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ], + "spectrum": "spectrum" + }, + "locked": { + "lastModified": 1752095991, + "narHash": "sha256-+paXzPg6SN3O+YKtQKiU+kQE1EkfsrI1XEYTxI4DSFk=", + "owner": "astro", + "repo": "microvm.nix", + "rev": "f30b1412b73df264dc9cac154d340645add350ff", + "type": "github" + }, + "original": { + "owner": "astro", + "repo": "microvm.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1751943650, + "narHash": "sha256-7orTnNqkGGru8Je6Un6mq1T8YVVU/O5kyW4+f9C1mZQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "88983d4b665fb491861005137ce2b11a9f89f203", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "microvm": "microvm", + "nixpkgs": "nixpkgs" + } + }, + "spectrum": { + "flake": false, + "locked": { + "lastModified": 1751265943, + "narHash": "sha256-XoHSo6GEElzRUOYAEg/jlh5c8TDsyDESFIux3nU/NMc=", + "ref": "refs/heads/main", + "rev": "37c8663fab86fdb202fece339ef7ac7177ffc201", + "revCount": 904, + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + }, + "original": { + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..dec8685 --- /dev/null +++ b/flake.nix @@ -0,0 +1,41 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + microvm = { + url = "github:astro/microvm.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + outputs = + { + microvm, + nixpkgs, + ... + }: + let + system = "x86_64-linux"; + pkgs = import nixpkgs { inherit system; }; + lib = nixpkgs.lib; + run-vm = pkgs.writeShellApplication { + name = "nix-vm"; + runtimeInputs = with pkgs; [ + jq + gum + ]; + text = builtins.readFile ./scripts/run-vm.sh; + }; + in + { + nixosConfigurations.demo = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + microvm.nixosModules.microvm + ./configuration.nix + ]; + }; + apps.x86_64-linux.run-vm = { + type = "app"; + program = "${lib.getExe run-vm}"; + }; + }; +} diff --git a/microvm.nix b/microvm.nix new file mode 100644 index 0000000..dd587b2 --- /dev/null +++ b/microvm.nix @@ -0,0 +1,40 @@ +_: { + + microvm = { + interfaces = [ + { + type = "user"; + + # interface name on the host + id = "vm-a1"; + + # Ethernet address of the MicroVM's interface, not the host's + # + # Locally administered have one of 2/6/A/E in the second nibble. + mac = "02:00:00:00:00:01"; + } + ]; + volumes = [ + { + mountPoint = "/var"; + image = "var.img"; + size = 256; + } + ]; + shares = [ + { + # use proto = "virtiofs" for MicroVMs that are started by systemd + proto = "9p"; + tag = "ro-store"; + # a host's /nix/store will be picked up so that no + # squashfs/erofs will be built for it. + source = "/nix/store"; + mountPoint = "/nix/.ro-store"; + } + ]; + + # "qemu" has 9p built-in! + hypervisor = "qemu"; + socket = "control.socket"; + }; +} diff --git a/scripts/run-vm.sh b/scripts/run-vm.sh new file mode 100644 index 0000000..acabbf9 --- /dev/null +++ b/scripts/run-vm.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v gum &> /dev/null; then + echo "gum (from charm.sh) is required but not found in PATH." + exit 1 +fi + +if ! command -v jq &> /dev/null; then + echo "jq is required but not found in PATH." + exit 1 +fi + +# List flake configs without evaluating them +HOSTS=() +while IFS= read -r line; do + HOSTS+=("$line") +done < <(nix flake show --json | jq -r '.nixosConfigurations | keys[]') + +if [ ${#HOSTS[@]} -eq 0 ]; then + echo "No NixOS configurations found in flake." + exit 1 +fi + +# Prompt user for a config +SELECTED=$(printf "%s\n" "${HOSTS[@]}" | gum choose --header="Select a NixOS VM config:") + +if [ -z "$SELECTED" ]; then + echo "No hostname selected. Exiting." + exit 1 +fi + +echo "Building VM for flake config: $SELECTED" + +# Build the VM +nix run ".#nixosConfigurations.$SELECTED.config.system.build.vm" + + diff --git a/vm-variant.nix b/vm-variant.nix new file mode 100644 index 0000000..c582a69 --- /dev/null +++ b/vm-variant.nix @@ -0,0 +1,32 @@ +_: { + + virtualisation.vmVariant = { + # virtualisation.diskImage = null; + # Boot with tmpfs as root + + fileSystems."/" = { + fsType = "tmpfs"; + options = [ + "defaults" + "size=1024M" + ]; + }; + virtualisation = { + + forwardPorts = [ + { + from = "host"; + host.port = 8888; + guest.port = 80; + } + ]; + graphics = false; # disables graphical output + memorySize = 1024; + }; + users.users = { + root = { + password = ""; + }; + }; + }; +}