2025-11-14 06:20:44 -03:00
|
|
|
{ self, virtwl, sidebus }:
|
2025-11-03 17:14:28 +01:00
|
|
|
{ pkgs, lib, utils, config, ... }: let
|
|
|
|
|
useTTY = {
|
|
|
|
|
TTYPath = "/dev/hvc0";
|
|
|
|
|
StandardOutput = "tty";
|
|
|
|
|
StandardInput = "tty";
|
|
|
|
|
StandardError = "tty";
|
|
|
|
|
};
|
|
|
|
|
runtimeDir = "/run/vm-user";
|
2025-11-28 02:06:09 -03:00
|
|
|
userbornConfig = {
|
|
|
|
|
groups = lib.mapAttrsToList (username: opts: {
|
|
|
|
|
inherit (opts) name gid members;
|
|
|
|
|
}) config.users.groups;
|
|
|
|
|
users = lib.mapAttrsToList (username: opts: {
|
|
|
|
|
inherit (opts)
|
|
|
|
|
name
|
|
|
|
|
uid
|
|
|
|
|
group
|
|
|
|
|
description
|
|
|
|
|
home
|
|
|
|
|
password
|
|
|
|
|
hashedPassword
|
|
|
|
|
hashedPasswordFile
|
|
|
|
|
initialPassword
|
|
|
|
|
initialHashedPassword
|
|
|
|
|
;
|
|
|
|
|
isNormal = opts.isNormalUser;
|
|
|
|
|
shell = utils.toShellPath opts.shell;
|
|
|
|
|
}) (lib.filterAttrs (_: u: u.enable) config.users.users);
|
|
|
|
|
};
|
|
|
|
|
userbornConfigJson = pkgs.writeText "userborn.json" (builtins.toJSON userbornConfig);
|
|
|
|
|
userbornResults = pkgs.runCommand "baked userborn" {} "mkdir -p $out; ${lib.getExe pkgs.userborn} ${userbornConfigJson} $out";
|
2025-11-03 17:14:28 +01:00
|
|
|
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;
|
|
|
|
|
services.udev.enable = lib.mkDefault true;
|
|
|
|
|
services.udev.packages = lib.mkDefault [];
|
2025-11-28 02:00:34 -03:00
|
|
|
environment.etc."resolv.conf".source = "/run/resolv.conf";
|
|
|
|
|
environment.etc."machine-id".source = "/run/machine-id";
|
2025-11-03 17:14:28 +01:00
|
|
|
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-udevd-kernel.socket"
|
|
|
|
|
"systemd-udevd-control.socket"
|
|
|
|
|
"systemd-udevd.service"
|
|
|
|
|
"systemd-tmpfiles-setup.service"
|
|
|
|
|
"user.slice"
|
|
|
|
|
];
|
|
|
|
|
upstreamWants = ["multi-user.target.wants"];
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-28 02:06:09 -03:00
|
|
|
# systemd.package = pkgs.systemdMinimal; # no analyze
|
2025-11-03 17:14:28 +01:00
|
|
|
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.microvm-nixos-activation = {
|
|
|
|
|
enable = true;
|
|
|
|
|
description = "NixOS Activation";
|
|
|
|
|
wantedBy = ["local-fs.target"];
|
2025-11-28 02:06:09 -03:00
|
|
|
before = ["systemd-tmpfiles-setup.service"];
|
|
|
|
|
requires = ["systemd-tmpfiles-setup.service"];
|
2025-11-03 17:14:28 +01:00
|
|
|
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
|
|
|
|
|
chown 1337:1337 /run
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-28 02:06:09 -03:00
|
|
|
# Configure user accounts
|
|
|
|
|
# The immutable overlay wants userborn or sysusers.. we just want baked-in files w/o running a service.
|
|
|
|
|
# So we can just run userborn at system closure build time!
|
|
|
|
|
systemd.sysusers.enable = false;
|
|
|
|
|
services.userborn.enable = true;
|
|
|
|
|
systemd.services.userborn.enable = false;
|
|
|
|
|
environment.etc."passwd" = lib.mkForce { source = "${userbornResults}/passwd"; mode = "0444"; };
|
|
|
|
|
environment.etc."group" = lib.mkForce { source = "${userbornResults}/group"; mode = "0444"; };
|
|
|
|
|
environment.etc."shadow" = lib.mkForce { source = "${userbornResults}/shadow"; mode = "0440"; };
|
2025-11-03 17:14:28 +01:00
|
|
|
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;
|
2025-11-14 02:09:04 -03:00
|
|
|
systemd.tmpfiles.rules = ["d ${runtimeDir} 0755 1337 1337 -"];
|
2025-11-03 17:14:28 +01:00
|
|
|
|
|
|
|
|
# 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";
|
2025-11-28 03:55:42 -03:00
|
|
|
PassEnvironment = ["TERM" "MESA_LOADER_DRIVER_OVERRIDE" "MUVM_REMOTE_CONFIG"]; # "KRUN_CONFIG"];
|
2025-11-14 06:20:44 -03:00
|
|
|
Environment = [
|
|
|
|
|
"XDG_RUNTIME_DIR=${runtimeDir}"
|
|
|
|
|
"WAYLAND_DISPLAY=wayland-1"
|
|
|
|
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=${runtimeDir}/sidebus.sock"
|
|
|
|
|
"PATH=/run/current-system/sw/bin"
|
|
|
|
|
];
|
2025-11-03 17:14:28 +01:00
|
|
|
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.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";
|
2025-11-28 01:54:58 -03:00
|
|
|
requires = ["wayland-proxy-virtwl.socket"];
|
2025-11-03 17:14:28 +01:00
|
|
|
serviceConfig = {
|
2025-11-28 01:54:58 -03:00
|
|
|
ExecStartPre = "+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128";
|
2025-11-14 06:17:34 -03:00
|
|
|
ExecStart = "${virtwl.packages.${pkgs.system}.proxy}/bin/wayland-proxy-virtwl --virtio-gpu";
|
2025-11-03 17:14:28 +01:00
|
|
|
Environment = ["XDG_RUNTIME_DIR=${runtimeDir}"];
|
|
|
|
|
User = "appvm";
|
|
|
|
|
Group = "appvm";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-14 06:20:44 -03:00
|
|
|
systemd.sockets.sidebus-agent = {
|
|
|
|
|
enable = true;
|
|
|
|
|
description = "D-Bus cross-domain proxy socket";
|
|
|
|
|
wantedBy = ["microvm.target"];
|
|
|
|
|
partOf = ["sidebus-agent.service"];
|
|
|
|
|
listenStreams = [ "${runtimeDir}/sidebus.sock" ];
|
|
|
|
|
socketConfig = {
|
|
|
|
|
SocketUser = "appvm";
|
|
|
|
|
SocketGroup = "appvm";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
systemd.services.sidebus-agent = {
|
|
|
|
|
enable = true;
|
|
|
|
|
description = "D-Bus cross-domain proxy";
|
|
|
|
|
requires = ["sidebus-agent.socket"];
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
ImportCredential = "sidebus.port";
|
|
|
|
|
ExecStart = "${sidebus.packages.${pkgs.system}.sidebus-agent}/bin/sidebus-agent";
|
|
|
|
|
User = "appvm";
|
|
|
|
|
Group = "appvm";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-03 17:14:28 +01:00
|
|
|
hardware.graphics.enable = true;
|
|
|
|
|
hardware.graphics.package = self.packages.${pkgs.system}.mesa;
|
|
|
|
|
}
|