clan-munix/flake.nix

356 lines
13 KiB
Nix
Raw Normal View History

2025-09-25 22:29:24 -03:00
{
inputs = {
self.submodules = true;
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# nixpkgs.url = "git+https://github.com/valpackett/nixpkgs?shallow=1&submodules=1&ref=..";
2025-09-25 22:29:24 -03:00
flake-utils.url = "github:numtide/flake-utils";
virtwl.url = "git+https://github.com/valpackett/wayland-proxy-virtwl?shallow=1&submodules=1&ref=wip";
virtwl.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, flake-utils, virtwl, ... }: {
nixosModules.default = { pkgs, lib, utils, config, ... }: let
useTTY = {
TTYPath = "/dev/hvc0";
StandardOutput = "tty";
StandardInput = "tty";
StandardError = "tty";
};
runtimeDir = "/run/vm-user";
in {
boot.isContainer = true;
fileSystems."/".device = lib.mkDefault "/dev/sda"; # dummy
# Disable unused things
environment.defaultPackages = lib.mkDefault [ ];
documentation = {
enable = lib.mkDefault false;
doc.enable = lib.mkDefault false;
info.enable = lib.mkDefault false;
man.enable = lib.mkDefault false;
nixos.enable = lib.mkDefault false;
};
services.logrotate.enable = false;
services.udisks2.enable = false;
system.tools.nixos-generate-config.enable = false;
system.activationScripts.specialfs = lib.mkForce "";
systemd.coredump.enable = false;
networking.firewall.enable = false;
powerManagement.enable = false;
boot.kexec.enable = false;
console.enable = false;
# Configure activation / systemd
boot.initrd.systemd.enable = true; # for etc.overlay, but we don't have initrd
system.etc.overlay.enable = true; # erofs
system.etc.overlay.mutable = false;
systemd.sysusers.enable = true;
services.userborn.enable = false;
services.udev.enable = lib.mkDefault true;
services.udev.packages = lib.mkDefault [];
environment.etc."resolv.conf".text = "# to be overridden with mount";
environment.etc."machine-id".text = "# to be overridden with mount";
environment.etc."systemd/system".source = lib.mkForce (utils.systemdUtils.lib.generateUnits {
type = "system";
units = config.systemd.units;
upstreamUnits = [
"sysinit.target"
"local-fs.target"
"nss-user-lookup.target"
"umount.target"
"shutdown.target"
"reboot.target"
"exit.target"
"final.target"
"systemd-exit.service"
"systemd-journald.socket"
"systemd-journald-audit.socket"
"systemd-journald-dev-log.socket"
"systemd-journald.service"
"systemd-sysusers.service"
"systemd-udevd-kernel.socket"
"systemd-udevd-control.socket"
"systemd-udevd.service"
"systemd-tmpfiles-setup.service"
"user.slice"
];
upstreamWants = ["multi-user.target.wants"];
});
# systemd.package = pkgs.systemdMinimal; # no sysusers
systemd.defaultUnit = "microvm.target";
systemd.targets.microvm = {
description = "Minimal microVM system";
wants = ["systemd-journald.socket" "systemd-udevd.service" "dbus.socket"];
unitConfig.AllowIsolate = "yes";
};
systemd.services.systemd-remount-fs.enable = lib.mkForce false;
systemd.services.systemd-pstore.enable = lib.mkForce false;
systemd.services.lastlog2-import.enable = lib.mkForce false;
systemd.services.suid-sgid-wrappers.enable = lib.mkForce false;
systemd.services.systemd-sysusers.serviceConfig = {
ExecStartPre = lib.mkForce [];
ExecStartPost = lib.mkForce [];
};
systemd.services.microvm-nixos-activation = {
enable = true;
description = "NixOS Activation";
wantedBy = ["local-fs.target"];
before = ["systemd-tmpfiles-setup.service" "systemd-sysusers.service"];
requires = ["systemd-tmpfiles-setup.service" "systemd-sysusers.service"];
unitConfig.DefaultDependencies = false;
serviceConfig = {
Type = "oneshot";
PassEnvironment = ["MICROVM_CLOSURE" "MICROVM_UID" "MICROVM_GID"];
} // useTTY;
script = ''
PATH=$MICROVM_CLOSURE/sw/bin
cp /etc/resolv.conf /run/
$MICROVM_CLOSURE/activate || true
mount --bind /run/resolv.conf /etc/resolv.conf
mount --bind /run/machine-id /etc/machine-id
chown 1337:1337 /run
'';
};
# Configure user account
users.mutableUsers = false;
users.users.appvm = {
uid = 1337;
group = "appvm";
isNormalUser = false;
isSystemUser = true;
home = "/home/appvm";
description = "microVM User";
extraGroups = [ "wheel" "video" "input" "systemd-journal" ];
};
users.groups.appvm.gid = 1337;
users.allowNoPasswordLogin = true;
systemd.tmpfiles.rules = ["d ${runtimeDir} 1337 1337 -"];
# Configure services
systemd.services.muvm-remote = {
enable = true;
description = "microVM Application runner";
onFailure = ["exit.target"];
onSuccess = ["exit.target"];
after = ["microvm-nixos-activation.service"];
wantedBy = ["microvm.target"];
serviceConfig = {
Type = "exec";
PassEnvironment = ["TERM" "MUVM_REMOTE_CONFIG"]; # "KRUN_CONFIG"];
Environment = ["XDG_RUNTIME_DIR=${runtimeDir}" "WAYLAND_DISPLAY=wayland-1" "PATH=/run/current-system/sw/bin"];
User = "appvm";
Group = "appvm";
ExecStart = "/opt/bin/muvm-remote";
ExecStopPost = ''+${pkgs.python3}/bin/python -c "import os,fcntl,struct;print(os.getenv('EXIT_STATUS', '1'));fcntl.ioctl(os.open('/', os.O_RDONLY), 0x7602, int(os.getenv('EXIT_STATUS', '1')))"'';
} // useTTY;
};
systemd.services.muvm-configure-network = {
enable = true;
description = "microVM Network configuration";
wantedBy = ["microvm.target"];
serviceConfig.Type = "oneshot";
serviceConfig.ExecStart = "/opt/bin/muvm-configure-network";
};
systemd.sockets.muvm-pwbridge = {
enable = true;
description = "PipeWire cross-domain proxy socket";
wantedBy = ["microvm.target"];
partOf = ["muvm-pwbridge.service"];
listenStreams = [ "${runtimeDir}/pipewire-0" ];
socketConfig = {
SocketUser = "appvm";
SocketGroup = "appvm";
};
};
systemd.services.muvm-pwbridge = {
enable = true;
description = "PipeWire cross-domain proxy";
requires = ["muvm-pwbridge.socket"];
serviceConfig.Type = "exec";
serviceConfig.ExecStart = "/opt/bin/muvm-pwbridge";
};
systemd.services.wait-for-udev = {
enable = true;
description = "Wait for device rules being applied";
wantedBy = ["microvm.target"];
requires = ["systemd-udevd.service"];
after = ["systemd-udevd.service"];
serviceConfig = {
Type = "oneshot";
ExecStart = [
"udevadm trigger --action=add"
"udevadm settle"
];
};
};
systemd.sockets.wayland-proxy-virtwl = {
enable = true;
description = "Wayland cross-domain proxy socket";
wantedBy = ["microvm.target"];
partOf = ["wayland-proxy-virtwl.service"];
listenStreams = [ "${runtimeDir}/wayland-1" ];
socketConfig = {
SocketUser = "appvm";
SocketGroup = "appvm";
FileDescriptorName = "wayland";
};
};
systemd.services.wayland-proxy-virtwl = {
enable = true;
description = "Wayland cross-domain proxy";
after = ["wait-for-udev.service"];
requires = ["wayland-proxy-virtwl.socket" "wait-for-udev.service"];
serviceConfig = {
ExecStart = "${virtwl.packages.x86_64-linux.proxy}/bin/wayland-proxy-virtwl --virtio-gpu";
Environment = ["XDG_RUNTIME_DIR=${runtimeDir}"];
User = "appvm";
Group = "appvm";
};
};
hardware.graphics.enable = true;
hardware.graphics.package = self.packages.${pkgs.system}.mesa;
};
} // flake-utils.lib.eachDefaultSystem (system:
2025-09-25 22:29:24 -03:00
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
2025-09-25 22:29:24 -03:00
};
in {
# packages.libkrunfw = pkgs.libkrunfw;
packages.libkrunfw = pkgs.libkrunfw.overrideAttrs (old: {
version = "5.0.0";
src = ./libkrunfw;
# src = pkgs.fetchFromGitHub {
# owner = "containers";
# repo = "libkrunfw";
# tag = "v4.10.0";
# hash = "sha256-mq2gw0+xL6qUZE/fk0vLT3PEpzPV8p+iwRFJHXVOMnk=";
# };
kernelSrc = pkgs.fetchurl {
url = "mirror://kernel/linux/kernel/v6.x/linux-6.12.44.tar.xz";
hash = "sha256-tlAhDtMCeyJJadFIqjd0Uqmq065/KFGr7dMa3+8Wva4=";
};
# buildInputs = old.buildInputs;
});
2025-09-25 22:29:24 -03:00
packages.libkrun = (pkgs.libkrun.override {
withBlk = true;
withGpu = true;
withSound = true;
withNet = true;
libkrunfw = self.packages.${system}.libkrunfw;
}).overrideAttrs (old: {
src = ./libkrun;
cargoDeps = pkgs.rustPlatform.importCargoLock {
lockFile = ./libkrun/Cargo.lock;
};
# mesonFlags = [ (pkgs.lib.mesonOption "decoders" "gles,vulkan,composer") ]; # no magma(?)
});
packages.muvm = (pkgs.muvm.override {
libkrun = self.packages.${system}.libkrun;
}).overrideAttrs (old: {
postPatch = ""; # no more sysctl; udevd now takes the var anyway; XXX: fex
MUVM_UDEVD_PATH = "${pkgs.systemd}/lib/systemd/systemd-udevd";
src = ./muvm;
cargoDeps = pkgs.rustPlatform.importCargoLock {
lockFile = ./muvm/Cargo.lock;
};
});
packages.munix = let
munixScript = (pkgs.writeScriptBin "munix" (builtins.readFile ./munix)).overrideAttrs(old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
});
in pkgs.symlinkJoin {
name = "munix";
paths = [ munixScript self.packages.${system}.muvm pkgs.passt pkgs.bubblewrap ];
2025-09-25 22:29:24 -03:00
buildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/munix --prefix PATH : $out/bin
'';
};
devShells.default = let
projects = with self.packages.${system}; [ libkrun muvm ];
in pkgs.mkShell {
MUVM_UDEVD_PATH = "${pkgs.systemd}/lib/systemd/systemd-udevd";
nativeBuildInputs = pkgs.lib.concatMap (pkg: pkg.nativeBuildInputs) projects;
buildInputs = (pkgs.lib.concatMap (pkg: pkg.buildInputs) projects) ++ (with self.packages.${system}; [
# virglrenderer
]) ++ (with pkgs; [
cargo
rust-analyzer
rustfmt
passt
bubblewrap
]);
};
packages.mesa = (pkgs.mesa.override {
vulkanDrivers = [
"amd"
"intel"
"microsoft-experimental" # removing this breaks the build
"nouveau"
"swrast"
"virtio"
"gfxstream" # probably not going to use this though
];
}).overrideAttrs (new: old: {
mesonFlags = old.mesonFlags ++ [ (pkgs.lib.mesonBool "amdgpu-virtio" true) ];
patches = old.patches ++ [ ./radvmmio.patch ]; # already merged to git
});
nixosConfigurations.testvm = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
self.nixosModules.default
({ ... }: {
2025-09-25 22:29:24 -03:00
system.stateVersion = "25.11";
fonts.packages = [ pkgs.adwaita-fonts pkgs.dejavu_fonts ];
2025-09-25 22:29:24 -03:00
environment.systemPackages = [
pkgs.fastfetch
pkgs.htop
virtwl.packages.x86_64-linux.proxy
pkgs.wayland-utils
pkgs.weston
pkgs.waycheck
pkgs.vulkan-tools
pkgs.glmark2
pkgs.mesa-demos
pkgs.xorg.xeyes
pkgs.xterm
# pkgs.vkquake # build broken: Program 'spirv-remap' not found
pkgs.veloren
2025-09-25 22:29:24 -03:00
pkgs.kdePackages.kate
pkgs.adwaita-icon-theme
pkgs.amberol
pkgs.bustle
pkgs.d-spy
2025-09-25 22:29:24 -03:00
pkgs.gnome-text-editor
pkgs.firefox
pkgs.ffmpeg-full
pkgs.mpv
pkgs.libva-utils
pkgs.tailscale
pkgs.zerotierone
pkgs.localsend
2025-09-25 22:29:24 -03:00
];
})
2025-09-25 22:29:24 -03:00
];
};
});
}