From 447ccad362e8d3c93b81b3a6da3ac4f0c0431a1e Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 9 Jan 2026 06:55:11 -0300 Subject: [PATCH 01/25] nix: devShell: add packages for proxy development --- devShells/default.nix | 52 +++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/devShells/default.nix b/devShells/default.nix index 7648228..382eb7b 100644 --- a/devShells/default.nix +++ b/devShells/default.nix @@ -1,17 +1,45 @@ -{ mkShell, lib, systemd, cargo, rust-analyzer, rustfmt, passt, bubblewrap, libkrun, muvm, sidebus-broker }: +{ + mkShell, + lib, + systemd, + cargo, + rust-analyzer, + rustfmt, + passt, + bubblewrap, + libkrun, + muvm, + sidebus-broker, + pkgs, +}: let - projects = [ libkrun muvm ]; -in mkShell { + projects = [ + libkrun + muvm + ]; +in +mkShell { MUVM_UDEVD_PATH = "${systemd}/lib/systemd/systemd-udevd"; nativeBuildInputs = lib.concatMap (pkg: pkg.nativeBuildInputs) projects; - buildInputs = (lib.concatMap (pkg: pkg.buildInputs) projects) ++ [ - # virglrenderer - cargo - rust-analyzer - rustfmt - passt - bubblewrap - sidebus-broker - ]; + buildInputs = + (lib.concatMap (pkg: pkg.buildInputs) projects) + ++ [ + # virglrenderer + cargo + rust-analyzer + rustfmt + passt + bubblewrap + sidebus-broker + ] + ++ (with pkgs; [ + meson + wayland + wayland-protocols + wayland-scanner + cairo + libgbm + ]); + # Enough things to compile wl-cross-domain-proxy, muvm, etc. in development } From c11c6c62920c2cedee75e31e1366b6b199bc207f Mon Sep 17 00:00:00 2001 From: Val Packett Date: Thu, 29 Jan 2026 20:54:42 -0300 Subject: [PATCH 02/25] nix: update inputs --- flake.lock | 30 +++++++++++++++--------------- flake.nix | 6 +++--- packages/libkrunfw/default.nix | 6 +++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index a5802ed..ffed8c6 100644 --- a/flake.lock +++ b/flake.lock @@ -59,61 +59,61 @@ "libkrun-src": { "flake": false, "locked": { - "lastModified": 1764837222, - "narHash": "sha256-Q4uFc3gvo6AuN1fAuUWU8k/+idOuDEj8Pkhm80wE798=", + "lastModified": 1767965092, + "narHash": "sha256-6HBSL5Zu29sDoEbZeQ6AsNIXUcqXVVGMk0AR2X6v1yU=", "owner": "containers", "repo": "libkrun", - "rev": "b250ee6fff7d959da3d55bb62ffe09d87248651c", + "rev": "376f25637c49f26231ec92532f31a24b99236aa6", "type": "github" }, "original": { "owner": "containers", "repo": "libkrun", - "rev": "b250ee6fff7d959da3d55bb62ffe09d87248651c", + "rev": "376f25637c49f26231ec92532f31a24b99236aa6", "type": "github" } }, "libkrunfw-src": { "flake": false, "locked": { - "lastModified": 1762790667, - "narHash": "sha256-tVQ0jGef8uJNo2L4Pmhy3ajVRKJ2Gs9oi44eOYAnmds=", + "lastModified": 1765874399, + "narHash": "sha256-x9HQP+EqCteoCq2Sl/TQcfdzQC5iuE4gaSKe7tN5dAA=", "owner": "containers", "repo": "libkrunfw", - "rev": "8a8c33f24f72aa6ca017347dc2be45b6fa612af5", + "rev": "20484a2e60290acb74c43ccfd6e1ea4caf41d470", "type": "github" }, "original": { "owner": "containers", "repo": "libkrunfw", - "rev": "8a8c33f24f72aa6ca017347dc2be45b6fa612af5", + "rev": "20484a2e60290acb74c43ccfd6e1ea4caf41d470", "type": "github" } }, "muvm-src": { "flake": false, "locked": { - "lastModified": 1763708092, - "narHash": "sha256-8K9XDnQbl/fh1Bsx1SwFuo5WVy5BztCjMPT6NW01lXQ=", + "lastModified": 1769336998, + "narHash": "sha256-ZFtAYwr3AaD8WsDmXJ6eU12UojzfMm50UBWmWIXstl0=", "owner": "valpackett", "repo": "muvm", - "rev": "3ec4c90bbfb6d0111f91b898a7f17deb562f4f92", + "rev": "ae7dbd49aac04e9732a14a424572e99a81eb1298", "type": "github" }, "original": { "owner": "valpackett", "repo": "muvm", - "rev": "3ec4c90bbfb6d0111f91b898a7f17deb562f4f92", + "rev": "ae7dbd49aac04e9732a14a424572e99a81eb1298", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1764242076, - "narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=", + "lastModified": 1769461804, + "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4", + "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 99ac54b..48acdaf 100644 --- a/flake.nix +++ b/flake.nix @@ -18,15 +18,15 @@ # To override with local checkouts during development, use the --override-input CLI flag! muvm-src = { - url = "github:valpackett/muvm/3ec4c90bbfb6d0111f91b898a7f17deb562f4f92"; + url = "github:valpackett/muvm/ae7dbd49aac04e9732a14a424572e99a81eb1298"; # v0.5.0+custom-init flake = false; }; libkrun-src = { - url = "github:containers/libkrun/b250ee6fff7d959da3d55bb62ffe09d87248651c"; + url = "github:containers/libkrun/376f25637c49f26231ec92532f31a24b99236aa6"; # v1.17.0 flake = false; }; libkrunfw-src = { - url = "github:containers/libkrunfw/8a8c33f24f72aa6ca017347dc2be45b6fa612af5"; + url = "github:containers/libkrunfw/20484a2e60290acb74c43ccfd6e1ea4caf41d470"; # v5.1.0 flake = false; }; }; diff --git a/packages/libkrunfw/default.nix b/packages/libkrunfw/default.nix index 668e016..d17d3b7 100644 --- a/packages/libkrunfw/default.nix +++ b/packages/libkrunfw/default.nix @@ -3,10 +3,10 @@ (libkrunfw.override { inherit variant; }).overrideAttrs (old: { - version = "5.0.0"; + version = "5.1.0"; src = libkrunfw-src; kernelSrc = fetchurl { - url = "mirror://kernel/linux/kernel/v6.x/linux-6.12.44.tar.xz"; - hash = "sha256-tlAhDtMCeyJJadFIqjd0Uqmq065/KFGr7dMa3+8Wva4="; + url = "mirror://kernel/linux/kernel/v6.x/linux-6.12.62.tar.xz"; + hash = "sha256-E+LGhayPq13Zkt0QVzJVTa5RSu81DCqMdBjnt062LBM="; }; }) From 40d82a0fd82a621d67acebbf49a0283b50f0a429 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Thu, 29 Jan 2026 23:26:36 -0300 Subject: [PATCH 03/25] nix: use static userborn as it's upstream now --- nixosModules/default.nix | 41 +--------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/nixosModules/default.nix b/nixosModules/default.nix index 9fb752c..78c7238 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -18,31 +18,6 @@ let StandardError = "tty"; }; runtimeDir = "/run/vm-user"; - 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"; system = pkgs.stdenv.hostPlatform.system; in { @@ -166,23 +141,9 @@ in }; # 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"; - }; + services.userborn.static = true; users.mutableUsers = false; users.users.appvm = { uid = 1337; From c89c9e4d9b4b067cf8ae915c35abfd6fb5ec76bd Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 01:39:11 -0300 Subject: [PATCH 04/25] nix: testvm: more test apps --- nixosModules/testvm.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nixosModules/testvm.nix b/nixosModules/testvm.nix index 786d915..5acee69 100644 --- a/nixosModules/testvm.nix +++ b/nixosModules/testvm.nix @@ -16,8 +16,8 @@ pkgs.mesa-demos pkgs.xorg.xeyes pkgs.xterm - # pkgs.vkquake # build broken: Program 'spirv-remap' not found - # pkgs.veloren # broken after update? + pkgs.vkquake + # pkgs.veloren pkgs.kdePackages.kate pkgs.adwaita-icon-theme pkgs.amberol @@ -33,5 +33,6 @@ pkgs.zerotierone pkgs.localsend pkgs.ashpd-demo + pkgs.wl-clipboard-rs ]; } From 13b2afcc14cb03a9d1cacf24c89616df2efba204 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 03:16:06 -0300 Subject: [PATCH 05/25] nix: add package for wl-cross-domain-proxy --- flake.nix | 2 + packages/wl-cross-domain-proxy/default.nix | 44 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 packages/wl-cross-domain-proxy/default.nix diff --git a/flake.nix b/flake.nix index 48acdaf..7b3fdbd 100644 --- a/flake.nix +++ b/flake.nix @@ -128,6 +128,8 @@ }; sidebus-agent = sidebus.packages.${system}.sidebus-agent; + + wl-cross-domain-proxy = pkgs.callPackage ./packages/wl-cross-domain-proxy { }; }; devShells.default = pkgs.callPackage ./devShells { diff --git a/packages/wl-cross-domain-proxy/default.nix b/packages/wl-cross-domain-proxy/default.nix new file mode 100644 index 0000000..0ca436b --- /dev/null +++ b/packages/wl-cross-domain-proxy/default.nix @@ -0,0 +1,44 @@ +{ + lib, + rustPlatform, + # fetchpatch, + fetchFromGitea, + pkg-config, + libdrm, +}: + +# TODO: upstream +rustPlatform.buildRustPackage { + pname = "wl-cross-domain-proxy"; + version = "0-unstable-2026-01-30"; + + src = fetchFromGitea { + domain = "codeberg.org"; + owner = "drakulix"; + repo = "wl-cross-domain-proxy"; + rev = "c6ce1ca89fb4d6f4f18d3aaf88324d40d4589177"; + hash = "sha256-ydyT4DFzWzhzOZR591UOgLjVQt/v6hRSNjzM3QtohlU="; + }; + + nativeBuildInputs = [ pkg-config ]; + + buildInputs = [ libdrm ]; + + cargoHash = "sha256-k3dmxIuCQoOrn/VwauTdzuRw/XKQB6LPLgO5ql0rE7E="; + cargoPatches = [ + # (fetchpatch { + # name = "XXX.patch"; + # url = "https://codeberg.org/drakulix/wl-cross-domain-proxy/pulls/XXX.patch"; + # hash = lib.fakeHash; + # }) + ]; + + meta = { + homepage = "https://codeberg.org/drakulix/wl-cross-domain-proxy"; + description = "Proxy for the wayland protocol across virtio-gpu cross-domain context"; + mainProgram = "wl-cross-domain-proxy"; + platforms = lib.platforms.linux; + license = [ lib.licenses.mit ]; + maintainers = [ lib.maintainers.valpackett ]; + }; +} From 9911b15fb7301c27a23be76daf11a9131229d868 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 03:16:48 -0300 Subject: [PATCH 06/25] nix: switch to wl-cross-domain-proxy --- nixosModules/default.nix | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/nixosModules/default.nix b/nixosModules/default.nix index 78c7238..f56a5f0 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -1,6 +1,5 @@ { self, - virtwl, sidebus, }: { @@ -223,11 +222,11 @@ in serviceConfig.ExecStart = "/opt/bin/muvm-pwbridge"; }; - systemd.sockets.wayland-proxy-virtwl = { + systemd.sockets.wayland-proxy = { enable = true; description = "Wayland cross-domain proxy socket"; wantedBy = [ "microvm.target" ]; - partOf = [ "wayland-proxy-virtwl.service" ]; + partOf = [ "wayland-proxy.service" ]; listenStreams = [ "${runtimeDir}/wayland-1" ]; socketConfig = { SocketUser = "appvm"; @@ -235,13 +234,13 @@ in FileDescriptorName = "wayland"; }; }; - systemd.services.wayland-proxy-virtwl = { + systemd.services.wayland-proxy = { enable = true; description = "Wayland cross-domain proxy"; - requires = [ "wayland-proxy-virtwl.socket" ]; + requires = [ "wayland-proxy.socket" ]; serviceConfig = { ExecStartPre = "+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128"; - ExecStart = "${virtwl.packages.${system}.proxy}/bin/wayland-proxy-virtwl --virtio-gpu"; + ExecStart = "${self.packages.${system}.wl-cross-domain-proxy}/bin/wl-cross-domain-proxy --listen-fd --filter-global wp_presentation"; User = "appvm"; Group = "appvm"; }; From 425ff896c80773b40cef7c1c65f502eedcaecb62 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 04:27:46 -0300 Subject: [PATCH 07/25] nix: deorbit virtwl-proxy --- flake.lock | 61 +---------------------------------------- flake.nix | 8 ++---- nixosModules/testvm.nix | 3 +- 3 files changed, 4 insertions(+), 68 deletions(-) diff --git a/flake.lock b/flake.lock index ffed8c6..5192622 100644 --- a/flake.lock +++ b/flake.lock @@ -38,24 +38,6 @@ "type": "github" } }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "libkrun-src": { "flake": false, "locked": { @@ -130,8 +112,7 @@ "libkrunfw-src": "libkrunfw-src", "muvm-src": "muvm-src", "nixpkgs": "nixpkgs", - "sidebus": "sidebus", - "virtwl": "virtwl" + "sidebus": "sidebus" } }, "rust-overlay": { @@ -193,46 +174,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "virtwl": { - "inputs": { - "flake-utils": "flake-utils_2", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1758075582, - "narHash": "sha256-o2lpXQLaM9QcZVr+sAxvh83CqJW1QkFhfja6K40ndmA=", - "ref": "wip", - "rev": "5a5df73a11b2f6bf671a8fc89926ac993e0fbb78", - "shallow": true, - "submodules": true, - "type": "git", - "url": "https://github.com/valpackett/wayland-proxy-virtwl" - }, - "original": { - "ref": "wip", - "shallow": true, - "submodules": true, - "type": "git", - "url": "https://github.com/valpackett/wayland-proxy-virtwl" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 7b3fdbd..c4ef335 100644 --- a/flake.nix +++ b/flake.nix @@ -10,9 +10,6 @@ flake-parts.url = "github:hercules-ci/flake-parts"; flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; - virtwl.url = "git+https://github.com/valpackett/wayland-proxy-virtwl?shallow=1&submodules=1&ref=wip"; - virtwl.inputs.nixpkgs.follows = "nixpkgs"; - sidebus.url = "git+https://git.clan.lol/clan/sidebus?shallow=1&ref=main"; sidebus.inputs.nixpkgs.follows = "nixpkgs"; @@ -36,7 +33,6 @@ self, nixpkgs, flake-parts, - virtwl, sidebus, muvm-src, libkrun-src, @@ -50,9 +46,9 @@ ]; flake = { - nixosModules.testvm = nixpkgs.lib.modules.importApply ./nixosModules/testvm.nix { inherit virtwl; }; + nixosModules.testvm = nixpkgs.lib.modules.importApply ./nixosModules/testvm.nix { }; nixosModules.default = nixpkgs.lib.modules.importApply ./nixosModules/default.nix { - inherit self virtwl sidebus; + inherit self sidebus; }; templates.musictest = { diff --git a/nixosModules/testvm.nix b/nixosModules/testvm.nix index 5acee69..4fa8c0d 100644 --- a/nixosModules/testvm.nix +++ b/nixosModules/testvm.nix @@ -1,4 +1,4 @@ -{ virtwl }: +{ }: { pkgs, ... }: { system.stateVersion = "25.11"; @@ -7,7 +7,6 @@ environment.systemPackages = [ pkgs.fastfetch pkgs.htop - virtwl.packages.${pkgs.stdenv.hostPlatform.system}.proxy pkgs.wayland-utils pkgs.weston pkgs.waycheck From 38213f4adab988424a6f124838c9b9903787b092 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 04:35:25 -0300 Subject: [PATCH 08/25] munix: add publish argument for port forwarding, fix #11 TODO: fix https://github.com/AsahiLinux/muvm/issues/178 as well --- munix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/munix b/munix index d10e091..e10b715 100755 --- a/munix +++ b/munix @@ -14,6 +14,7 @@ GPU=1 WAYLAND=1 PIPEWIRE=1 X11=0 +USING_PUBLISH=0 export TMP=/tmp TMPDIR=/tmp TEMP=/tmp TEMPDIR=/tmp LC_ALL=C if [ ! -e "$HOST_OPENGL_DRIVER" ]; then @@ -32,6 +33,7 @@ while [ "$#" -gt 0 ]; do --ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); shift 3;; --expose) BWRAP_ARGS+=("--bind" "$2" "$2"); shift 2;; --ro-expose) BWRAP_ARGS+=("--ro-bind" "$2" "$2"); shift 2;; + -p|--publish) USING_PUBLISH=1; MUVM_ARGS+=("--publish=$2"); shift 2;; --host-opengl-driver) HOST_OPENGL_DRIVER="$2"; shift 2;; --munix-bin-dir) SCRIPT_PATH="$2"; shift 2;; --muvm-bin-dir) MUVM_PATH="$2"; shift 2;; @@ -177,6 +179,10 @@ BWRAP_ARGS+=( --bind "$HOST_RUNTIME_DIR/port.sock" "$XDG_RUNTIME_DIR/krun/socket/port-50000" ) +if [ "$USING_PUBLISH" -eq 1 ]; then + printf "\n\n\n\e[1mNote: due to a \e[31mBUG\e[39m with port publishing (-p) you have to send the first outgoing packet (e.g. ping -c1 8.8.8.8) before your ports start receiving traffic. Sorry for the inconvenience!\e[39;0m\n\n\n\n" >&2 +fi + # do not 'exec' because of cleanup :) bwrap --unshare-all --share-net \ --uid $MICROVM_UID --gid $MICROVM_GID \ From 8113c269cb738ea3e63131f081e744593b80c171 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 05:45:02 -0300 Subject: [PATCH 09/25] munix: add more arg shorthands --- munix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/munix b/munix index e10b715..14e777d 100755 --- a/munix +++ b/munix @@ -29,9 +29,9 @@ while [ "$#" -gt 0 ]; do --no-wayland) WAYLAND=0; shift 1;; --no-pipewire) PIPEWIRE=0; shift 1;; --x11) X11=1; shift 1;; - --bind) BWRAP_ARGS+=("--bind" "$2" "$3"); shift 3;; + -b|--bind) BWRAP_ARGS+=("--bind" "$2" "$3"); shift 3;; --ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); shift 3;; - --expose) BWRAP_ARGS+=("--bind" "$2" "$2"); shift 2;; + -e|--expose) BWRAP_ARGS+=("--bind" "$2" "$2"); shift 2;; --ro-expose) BWRAP_ARGS+=("--ro-bind" "$2" "$2"); shift 2;; -p|--publish) USING_PUBLISH=1; MUVM_ARGS+=("--publish=$2"); shift 2;; --host-opengl-driver) HOST_OPENGL_DRIVER="$2"; shift 2;; From a82b0de3101c6167a9483cf6c07247c2e18d1b53 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 05:47:28 -0300 Subject: [PATCH 10/25] munix: set wayland/pw/portal enablement variables for toolkits by default --- munix | 22 ++++++++++++++++++++++ nixosModules/default.nix | 13 +++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/munix b/munix index 14e777d..241073b 100755 --- a/munix +++ b/munix @@ -14,6 +14,7 @@ GPU=1 WAYLAND=1 PIPEWIRE=1 X11=0 +ENV_DEFAULTS=1 USING_PUBLISH=0 export TMP=/tmp TMPDIR=/tmp TEMP=/tmp TEMPDIR=/tmp LC_ALL=C @@ -28,6 +29,7 @@ while [ "$#" -gt 0 ]; do --no-gpu) GPU=0; shift 1;; --no-wayland) WAYLAND=0; shift 1;; --no-pipewire) PIPEWIRE=0; shift 1;; + --no-env-defaults) ENV_DEFAULTS=0; shift 1;; --x11) X11=1; shift 1;; -b|--bind) BWRAP_ARGS+=("--bind" "$2" "$3"); shift 3;; --ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); shift 3;; @@ -125,6 +127,15 @@ if [ "$WAYLAND" -eq 1 ]; then "--setenv" "WAYLAND_DISPLAY" "$WAYLAND_DISPLAY" ) MUVM_ARGS+=("-e" "WAYLAND_DISPLAY=wayland-1") # the proxy is managed by us, not muvm + if [ "$ENV_DEFAULTS" -eq 1 ]; then + MUVM_ARGS+=( + "-e" "XDG_SESSION_TYPE=wayland" + "-e" "SDL_VIDEODRIVER=wayland" + "-e" "QT_QPA_PLATFORM=wayland" + "-e" "_JAVA_AWT_WM_NONREPARENTING=1" # e.g. with xwayland-satellite + "-e" "ELECTRON_OZONE_PLATFORM_HINT=wayland" # 28 < Electron < 39; newer should work by default + ) + fi fi if [ "$PIPEWIRE" -eq 1 ]; then @@ -142,6 +153,11 @@ if [ "$PIPEWIRE" -eq 1 ]; then PIPEWIRE_REMOTE=pipewire-0 fi BWRAP_ARGS+=("--bind" "$PIPEWIRE_RUNTIME_DIR/$PIPEWIRE_REMOTE" "$PIPEWIRE_RUNTIME_DIR/$PIPEWIRE_REMOTE") + if [ "$ENV_DEFAULTS" -eq 1 ]; then + MUVM_ARGS+=( + "-e" "SDL_AUDIO_DRIVER=pipewire" + ) + fi fi if [ "$X11" -eq 1 ]; then @@ -178,6 +194,12 @@ BWRAP_ARGS+=( --bind "$HOST_RUNTIME_DIR" /mnt/munix-doc-portal --bind "$HOST_RUNTIME_DIR/port.sock" "$XDG_RUNTIME_DIR/krun/socket/port-50000" ) +if [ "$ENV_DEFAULTS" -eq 1 ]; then + MUVM_ARGS+=( + "-e" "GTK_USE_PORTAL=1" # GTK 3 including Firefox + "-e" "QT_QPA_PLATFORMTHEME=xdgdesktopportal" + ) +fi if [ "$USING_PUBLISH" -eq 1 ]; then printf "\n\n\n\e[1mNote: due to a \e[31mBUG\e[39m with port publishing (-p) you have to send the first outgoing packet (e.g. ping -c1 8.8.8.8) before your ports start receiving traffic. Sorry for the inconvenience!\e[39;0m\n\n\n\n" >&2 diff --git a/nixosModules/default.nix b/nixosModules/default.nix index f56a5f0..217a3ed 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -177,10 +177,19 @@ in serviceConfig = { Type = "exec"; PassEnvironment = [ - "TERM" "MESA_LOADER_DRIVER_OVERRIDE" "MUVM_REMOTE_CONFIG" - ]; # "KRUN_CONFIG"]; + # "KRUN_CONFIG" + + "TERM" + "XDG_SESSION_TYPE" + "SDL_VIDEODRIVER" + "QT_QPA_PLATFORM" + "_JAVA_AWT_WM_NONREPARENTING" + "ELECTRON_OZONE_PLATFORM_HINT" + "GTK_USE_PORTAL" + "QT_QPA_PLATFORMTHEME" + ]; Environment = [ "WAYLAND_DISPLAY=wayland-1" "DBUS_SESSION_BUS_ADDRESS=unix:path=${runtimeDir}/dbus.sock" From 585970fe9204fe43d695b048da773252d2777af3 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 06:11:21 -0300 Subject: [PATCH 11/25] munix: do not set display from the script It is now entirely managed by systemd. --- munix | 1 - 1 file changed, 1 deletion(-) diff --git a/munix b/munix index 241073b..9c67084 100755 --- a/munix +++ b/munix @@ -126,7 +126,6 @@ if [ "$WAYLAND" -eq 1 ]; then "--bind" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "--setenv" "WAYLAND_DISPLAY" "$WAYLAND_DISPLAY" ) - MUVM_ARGS+=("-e" "WAYLAND_DISPLAY=wayland-1") # the proxy is managed by us, not muvm if [ "$ENV_DEFAULTS" -eq 1 ]; then MUVM_ARGS+=( "-e" "XDG_SESSION_TYPE=wayland" From 67666b8f46fbbb59d0756bcaf1fc964101bf8fe8 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 30 Jan 2026 06:12:47 -0300 Subject: [PATCH 12/25] nix: update sidebus and flake-parts sidebus now uses flake-parts too --- flake.lock | 73 ++++++++---------------------------------------------- flake.nix | 1 + 2 files changed, 11 insertions(+), 63 deletions(-) diff --git a/flake.lock b/flake.lock index 5192622..7f03055 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1768135262, - "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", + "lastModified": 1769996383, + "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", + "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", "type": "github" }, "original": { @@ -20,24 +20,6 @@ "type": "github" } }, - "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" - } - }, "libkrun-src": { "flake": false, "locked": { @@ -115,40 +97,20 @@ "sidebus": "sidebus" } }, - "rust-overlay": { + "sidebus": { "inputs": { + "flake-parts": [ + "flake-parts" + ], "nixpkgs": [ - "sidebus", "nixpkgs" ] }, "locked": { - "lastModified": 1763087910, - "narHash": "sha256-eB9Z1mWd1U6N61+F8qwDggX0ihM55s4E0CluwNukJRU=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "cf4a68749733d45c0420726596367acd708eb2e8", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "sidebus": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ], - "rust-overlay": "rust-overlay" - }, - "locked": { - "lastModified": 1765527875, - "narHash": "sha256-QKsl+TAjdd1qk8Nd9mlByz07S+kGi8voSxxTdUNjt6A=", + "lastModified": 1770365107, + "narHash": "sha256-rp2hDKF3pwHN0lBr09ckMNaMSJnwNolQmiad8C7u41Q=", "ref": "main", - "rev": "c9095421c6ec33e7293879d2df9d050991200803", + "rev": "26261306592f6173fb844083b396bebf8140cb2b", "shallow": true, "type": "git", "url": "https://git.clan.lol/clan/sidebus" @@ -159,21 +121,6 @@ "type": "git", "url": "https://git.clan.lol/clan/sidebus" } - }, - "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", diff --git a/flake.nix b/flake.nix index c4ef335..687042e 100644 --- a/flake.nix +++ b/flake.nix @@ -12,6 +12,7 @@ sidebus.url = "git+https://git.clan.lol/clan/sidebus?shallow=1&ref=main"; sidebus.inputs.nixpkgs.follows = "nixpkgs"; + sidebus.inputs.flake-parts.follows = "flake-parts"; # To override with local checkouts during development, use the --override-input CLI flag! muvm-src = { From 9708e5fb6464ea1d9f8f5928c2eb843ff6f33746 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Sat, 7 Feb 2026 00:17:41 -0300 Subject: [PATCH 13/25] nix: update nixpkgs now includes the most recent libkrun(fw) releases --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 7f03055..321368e 100644 --- a/flake.lock +++ b/flake.lock @@ -73,11 +73,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1769461804, - "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", + "lastModified": 1770197578, + "narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", + "rev": "00c21e4c93d963c50d4c0c89bfa84ed6e0694df2", "type": "github" }, "original": { From 09f1eb76de75d892d60280231a9350d4700a7a15 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Sat, 7 Feb 2026 00:21:36 -0300 Subject: [PATCH 14/25] nix: comment out libkrun(fw) source overrides As we're currently using entirely upstream ones right now. Let's reuse the cache.nixos.org builds. --- flake.lock | 36 ------------------------------ flake.nix | 24 ++++++++++---------- packages/libkrun/default.nix | 40 ++++++++++++++++++++++------------ packages/libkrunfw/default.nix | 30 ++++++++++++++++--------- 4 files changed, 58 insertions(+), 72 deletions(-) diff --git a/flake.lock b/flake.lock index 321368e..ebbd7e5 100644 --- a/flake.lock +++ b/flake.lock @@ -20,40 +20,6 @@ "type": "github" } }, - "libkrun-src": { - "flake": false, - "locked": { - "lastModified": 1767965092, - "narHash": "sha256-6HBSL5Zu29sDoEbZeQ6AsNIXUcqXVVGMk0AR2X6v1yU=", - "owner": "containers", - "repo": "libkrun", - "rev": "376f25637c49f26231ec92532f31a24b99236aa6", - "type": "github" - }, - "original": { - "owner": "containers", - "repo": "libkrun", - "rev": "376f25637c49f26231ec92532f31a24b99236aa6", - "type": "github" - } - }, - "libkrunfw-src": { - "flake": false, - "locked": { - "lastModified": 1765874399, - "narHash": "sha256-x9HQP+EqCteoCq2Sl/TQcfdzQC5iuE4gaSKe7tN5dAA=", - "owner": "containers", - "repo": "libkrunfw", - "rev": "20484a2e60290acb74c43ccfd6e1ea4caf41d470", - "type": "github" - }, - "original": { - "owner": "containers", - "repo": "libkrunfw", - "rev": "20484a2e60290acb74c43ccfd6e1ea4caf41d470", - "type": "github" - } - }, "muvm-src": { "flake": false, "locked": { @@ -90,8 +56,6 @@ "root": { "inputs": { "flake-parts": "flake-parts", - "libkrun-src": "libkrun-src", - "libkrunfw-src": "libkrunfw-src", "muvm-src": "muvm-src", "nixpkgs": "nixpkgs", "sidebus": "sidebus" diff --git a/flake.nix b/flake.nix index 687042e..a7bacf1 100644 --- a/flake.nix +++ b/flake.nix @@ -19,14 +19,14 @@ url = "github:valpackett/muvm/ae7dbd49aac04e9732a14a424572e99a81eb1298"; # v0.5.0+custom-init flake = false; }; - libkrun-src = { - url = "github:containers/libkrun/376f25637c49f26231ec92532f31a24b99236aa6"; # v1.17.0 - flake = false; - }; - libkrunfw-src = { - url = "github:containers/libkrunfw/20484a2e60290acb74c43ccfd6e1ea4caf41d470"; # v5.1.0 - flake = false; - }; + # libkrun-src = { + # url = "github:containers/libkrun/376f25637c49f26231ec92532f31a24b99236aa6"; # v1.17.0 + # flake = false; + # }; + # libkrunfw-src = { + # url = "github:containers/libkrunfw/20484a2e60290acb74c43ccfd6e1ea4caf41d470"; # v5.1.0 + # flake = false; + # }; }; outputs = @@ -36,8 +36,8 @@ flake-parts, sidebus, muvm-src, - libkrun-src, - libkrunfw-src, + # libkrun-src, + # libkrunfw-src, ... }: flake-parts.lib.mkFlake { inherit inputs; } { @@ -103,12 +103,12 @@ # Packages support variant parameter: null (default), "sev", or "tdx" # To build a variant: packages.libkrunfw.override { variant = "sev"; } libkrunfw = pkgs.callPackage ./packages/libkrunfw { - libkrunfw-src = libkrunfw-src; + # libkrunfw-src = libkrunfw-src; }; libkrun = pkgs.callPackage ./packages/libkrun { libkrunfw = self'.packages.libkrunfw; - libkrun-src = libkrun-src; + # libkrun-src = libkrun-src; }; mesa = pkgs.callPackage ./packages/mesa { }; diff --git a/packages/libkrun/default.nix b/packages/libkrun/default.nix index dde2c4c..205f8d2 100644 --- a/packages/libkrun/default.nix +++ b/packages/libkrun/default.nix @@ -1,18 +1,30 @@ -{ libkrun, libkrunfw, libkrun-src, rustPlatform, variant ? null, ... }: +{ + libkrun, + libkrunfw, + # libkrun-src, + # rustPlatform, + variant ? null, + ... +}: let libkrunfw' = libkrunfw.override { inherit variant; }; -in -(libkrun.override { - withBlk = true; - withGpu = true; - withSound = true; - withNet = true; - inherit variant; - libkrunfw = libkrunfw'; -}).overrideAttrs (old: { - src = libkrun-src; - cargoDeps = rustPlatform.importCargoLock { - lockFile = "${libkrun-src}/Cargo.lock"; + libkrun' = libkrun.override { + withBlk = true; + withNet = true; + withGpu = true; + # --- stick to the override used in nixpkgs' muvm package to reuse nixos.org cache when not overriding src --- + # withSound = true; # not for pipewire forwarding, anyway + # withTimesync = true; # why not?.. + # --------- + inherit variant; + libkrunfw = libkrunfw'; }; -}) +in +libkrun' +# libkrun'.overrideAttrs (old: { +# src = libkrun-src; +# cargoDeps = rustPlatform.importCargoLock { +# lockFile = "${libkrun-src}/Cargo.lock"; +# }; +# }) diff --git a/packages/libkrunfw/default.nix b/packages/libkrunfw/default.nix index d17d3b7..c805728 100644 --- a/packages/libkrunfw/default.nix +++ b/packages/libkrunfw/default.nix @@ -1,12 +1,22 @@ -{ libkrunfw, libkrunfw-src, fetchurl, variant ? null, ... }: +{ + libkrunfw, + # libkrunfw-src, + # fetchurl, + variant ? null, + ... +}: -(libkrunfw.override { - inherit variant; -}).overrideAttrs (old: { - version = "5.1.0"; - src = libkrunfw-src; - kernelSrc = fetchurl { - url = "mirror://kernel/linux/kernel/v6.x/linux-6.12.62.tar.xz"; - hash = "sha256-E+LGhayPq13Zkt0QVzJVTa5RSu81DCqMdBjnt062LBM="; +let + libkrunfw' = libkrunfw.override { + inherit variant; }; -}) +in +libkrunfw' +# libkrunfw'.overrideAttrs (old: { +# version = "5.1.0"; +# src = libkrunfw-src; +# kernelSrc = fetchurl { +# url = "mirror://kernel/linux/kernel/v6.x/linux-6.12.62.tar.xz"; +# hash = "sha256-E+LGhayPq13Zkt0QVzJVTa5RSu81DCqMdBjnt062LBM="; +# }; +# }) From 53f827553f9f98fe1f2509fba0c137d8b91271d9 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Sat, 7 Feb 2026 01:17:24 -0300 Subject: [PATCH 15/25] nix: add nautilus to testvm Will be useful for testing drag-out --- nixosModules/testvm.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nixosModules/testvm.nix b/nixosModules/testvm.nix index 4fa8c0d..b38340a 100644 --- a/nixosModules/testvm.nix +++ b/nixosModules/testvm.nix @@ -32,6 +32,7 @@ pkgs.zerotierone pkgs.localsend pkgs.ashpd-demo + pkgs.nautilus pkgs.wl-clipboard-rs ]; } From 820fcd3da1b98bb99c84a4138062daffc8efccdf Mon Sep 17 00:00:00 2001 From: Val Packett Date: Sat, 7 Feb 2026 01:25:06 -0300 Subject: [PATCH 16/25] nix: chase removal of etc overlay symlinks, fixes #14 --- nixosModules/default.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nixosModules/default.nix b/nixosModules/default.nix index 217a3ed..3b229dd 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -53,6 +53,11 @@ in 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; + system.systemBuilderCommands = # XXX: removed with the introduction of nixos-init + '' + ln -s ${config.system.build.etcMetadataImage} $out/etc-metadata-image + ln -s ${config.system.build.etcBasedir} $out/etc-basedir + ''; system.switch.enable = false; services.udev.enable = lib.mkDefault true; services.udev.packages = lib.mkDefault [ ]; From 322b6efc1c9d26f238cfbe9266f6c3d099e909fa Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 13 Feb 2026 14:55:32 -0300 Subject: [PATCH 17/25] nix: testvm: update stateVersion, add rewaita (theme coloring for demos) --- nixosModules/testvm.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nixosModules/testvm.nix b/nixosModules/testvm.nix index b38340a..466cff5 100644 --- a/nixosModules/testvm.nix +++ b/nixosModules/testvm.nix @@ -1,6 +1,6 @@ { }: { pkgs, ... }: { - system.stateVersion = "25.11"; + system.stateVersion = "26.05"; fonts.packages = [ pkgs.adwaita-fonts pkgs.dejavu_fonts ]; programs.dconf.enable = true; @@ -33,6 +33,7 @@ pkgs.localsend pkgs.ashpd-demo pkgs.nautilus + pkgs.rewaita pkgs.wl-clipboard-rs ]; } From 8c3878f117b1e30f3eb97d95f1095fb74ce634d9 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 13 Feb 2026 14:55:52 -0300 Subject: [PATCH 18/25] Pass timezone through to the VM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What a way to discover that this was missing- PipeWire camera was freezing unless something on the host was already streaming it… gstclock.c:1086:gst_clock_get_internal_time: internal time 1:01:04.622699903 gstclock.c:1129:gst_clock_get_time: adjusted time 5123776:20:12.866176008 Well, that wasn't even caused by the TZ but it made me think to fix it.. NOTE for local dev, rebuild micro-activate now --- micro-activate.rs | 2 ++ munix | 4 +++- nixosModules/default.nix | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/micro-activate.rs b/micro-activate.rs index d9d829c..0806e96 100644 --- a/micro-activate.rs +++ b/micro-activate.rs @@ -71,6 +71,7 @@ fn main() -> Result<(), std::io::Error> { // // Let's preserve the fixed passed-in files and set up the NixOS symlinks in the new mount. let resolv_conf = std::fs::read("/run/resolv.conf")?; + let localtime = std::fs::read("/run/localtime")?; assert_eq!( unsafe { mount( @@ -83,6 +84,7 @@ fn main() -> Result<(), std::io::Error> { }, 0 ); + std::fs::write("/run/localtime", &localtime)?; std::fs::write("/run/resolv.conf", &resolv_conf)?; std::fs::write("/run/machine-id", &gen_machine_id())?; std::os::unix::fs::symlink(&closure, "/run/current-system")?; diff --git a/munix b/munix index 9c67084..89d79c3 100755 --- a/munix +++ b/munix @@ -223,6 +223,7 @@ bwrap --unshare-all --share-net \ --symlink "$MICROVM_CLOSURE" /run/current-system \ --ro-bind /nix/store /nix/store \ --file 13 /run/resolv.conf \ + --file 14 /run/localtime \ --dir "$XDG_RUNTIME_DIR" \ --setenv PATH "/run/munix/muvm:/run/munix/passt:$MICROVM_CLOSURE/sw/bin" \ "${BWRAP_ARGS[@]}" \ @@ -233,4 +234,5 @@ bwrap --unshare-all --share-net \ -e MICROVM_CLOSURE="$MICROVM_CLOSURE" \ -e MICROVM_UID="$MICROVM_UID" -e MICROVM_GID="$MICROVM_GID" \ -i -t -- "${MICROVM_COMMAND[@]}" \ - 13< /etc/resolv.conf + 13< /etc/resolv.conf \ + 14< /etc/localtime diff --git a/nixosModules/default.nix b/nixosModules/default.nix index 3b229dd..15a5a08 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -64,6 +64,7 @@ in services.resolved.enable = false; environment.etc."resolv.conf".source = "/run/resolv.conf"; environment.etc."machine-id".source = "/run/machine-id"; + environment.etc."localtime".source = "/run/localtime"; environment.etc."systemd/system".source = lib.mkForce ( utils.systemdUtils.lib.generateUnits { type = "system"; From 981393443b1baf5538698351516300d9e5c0a1c7 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 20 Feb 2026 04:12:54 -0300 Subject: [PATCH 19/25] Set up a monotonic clock boot time offset in the VM --- micro-activate.rs | 14 ++++++++++++++ munix | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/micro-activate.rs b/micro-activate.rs index 0806e96..776dae4 100644 --- a/micro-activate.rs +++ b/micro-activate.rs @@ -8,6 +8,8 @@ const MS_NODEV: c_ulong = 0x04; const MS_RELATIME: c_ulong = 0x200000; const MS_STRICTATIME: c_ulong = 0x1000000; +const CLONE_NEWTIME: c_int = 0x80; + unsafe extern "C" { fn mount( src: *const c_char, @@ -17,6 +19,7 @@ unsafe extern "C" { data: *const c_void, ) -> c_int; fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> c_int; + fn unshare(flags: c_int) -> c_int; } fn gen_machine_id() -> String { @@ -133,6 +136,17 @@ fn main() -> Result<(), std::io::Error> { ); } + if let Ok(offset) = std::env::var("BOOT_TIME_OFFSET") { + if unsafe { unshare(CLONE_NEWTIME) } != 0 { + eprintln!("[micro-activate] Could not unshare time!"); + } else { + std::fs::write( + "/proc/self/timens_offsets", + format!("monotonic {offset}\nboottime {offset}\n"), + )?; + } + } + let mut args = std::env::args_os().skip(1); let cmd = args.next().unwrap(); Err(std::process::Command::new(cmd).args(args).exec()) diff --git a/munix b/munix index 89d79c3..4f26980 100755 --- a/munix +++ b/munix @@ -204,6 +204,10 @@ if [ "$USING_PUBLISH" -eq 1 ]; then printf "\n\n\n\e[1mNote: due to a \e[31mBUG\e[39m with port publishing (-p) you have to send the first outgoing packet (e.g. ping -c1 8.8.8.8) before your ports start receiving traffic. Sorry for the inconvenience!\e[39;0m\n\n\n\n" >&2 fi +# xxx: some time is lost to the starting process.. +[[ "$( Date: Tue, 24 Feb 2026 11:08:33 +0100 Subject: [PATCH 20/25] fix(template): use structured settings for MPD audio output Replace deprecated extraConfig with settings.audio_output --- templates/musictest/flake.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/musictest/flake.nix b/templates/musictest/flake.nix index a2c7759..406049b 100644 --- a/templates/musictest/flake.nix +++ b/templates/musictest/flake.nix @@ -46,12 +46,12 @@ musicDirectory = "/etc/demo-music"; user = "appvm"; group = "appvm"; - extraConfig = '' - audio_output { - type "pipewire" - name "Pipewire Output" + settings.audio_output = [ + { + type = "pipewire"; + name = "Pipewire Output"; } - ''; + ]; }; environment.etc."demo-music/0101GhostsI.ogg".source = pkgs.fetchurl { # just a CC-BY-SA licensed example From beeb5f5d9ffbcaf1fb6aec66ac74e34a0148b31c Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 20 Feb 2026 05:17:28 -0300 Subject: [PATCH 21/25] Fork libkrun again to fix buffer mapping permission issue (fix #18) Initial D-Bus WIP is also there.. --- flake.lock | 18 ++++++++++++++++++ flake.nix | 12 ++++++------ packages/libkrun/default.nix | 20 +++++++++++--------- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index ebbd7e5..84f1720 100644 --- a/flake.lock +++ b/flake.lock @@ -20,6 +20,23 @@ "type": "github" } }, + "libkrun-src": { + "flake": false, + "locked": { + "lastModified": 1772170018, + "narHash": "sha256-pi4Mrx9wFE8zT8lx+0su2bP1tTkJBh5FaGNQjAFUAx4=", + "owner": "valpackett", + "repo": "libkrun", + "rev": "eeafbc55379b60379414168e7a22d5f95b73d7a0", + "type": "github" + }, + "original": { + "owner": "valpackett", + "repo": "libkrun", + "rev": "eeafbc55379b60379414168e7a22d5f95b73d7a0", + "type": "github" + } + }, "muvm-src": { "flake": false, "locked": { @@ -56,6 +73,7 @@ "root": { "inputs": { "flake-parts": "flake-parts", + "libkrun-src": "libkrun-src", "muvm-src": "muvm-src", "nixpkgs": "nixpkgs", "sidebus": "sidebus" diff --git a/flake.nix b/flake.nix index a7bacf1..84c3166 100644 --- a/flake.nix +++ b/flake.nix @@ -19,10 +19,10 @@ url = "github:valpackett/muvm/ae7dbd49aac04e9732a14a424572e99a81eb1298"; # v0.5.0+custom-init flake = false; }; - # libkrun-src = { - # url = "github:containers/libkrun/376f25637c49f26231ec92532f31a24b99236aa6"; # v1.17.0 - # flake = false; - # }; + libkrun-src = { + url = "github:valpackett/libkrun/eeafbc55379b60379414168e7a22d5f95b73d7a0"; # PR #558 (map permission fix) + D-Bus WIP + flake = false; + }; # libkrunfw-src = { # url = "github:containers/libkrunfw/20484a2e60290acb74c43ccfd6e1ea4caf41d470"; # v5.1.0 # flake = false; @@ -36,7 +36,7 @@ flake-parts, sidebus, muvm-src, - # libkrun-src, + libkrun-src, # libkrunfw-src, ... }: @@ -108,7 +108,7 @@ libkrun = pkgs.callPackage ./packages/libkrun { libkrunfw = self'.packages.libkrunfw; - # libkrun-src = libkrun-src; + libkrun-src = libkrun-src; }; mesa = pkgs.callPackage ./packages/mesa { }; diff --git a/packages/libkrun/default.nix b/packages/libkrun/default.nix index 205f8d2..00d655c 100644 --- a/packages/libkrun/default.nix +++ b/packages/libkrun/default.nix @@ -1,8 +1,9 @@ { libkrun, libkrunfw, - # libkrun-src, - # rustPlatform, + libkrun-src, + rustPlatform, + libcap_ng, variant ? null, ... }: @@ -21,10 +22,11 @@ let libkrunfw = libkrunfw'; }; in -libkrun' -# libkrun'.overrideAttrs (old: { -# src = libkrun-src; -# cargoDeps = rustPlatform.importCargoLock { -# lockFile = "${libkrun-src}/Cargo.lock"; -# }; -# }) +# libkrun' +libkrun'.overrideAttrs (old: { + src = libkrun-src; + cargoDeps = rustPlatform.importCargoLock { + lockFile = "${libkrun-src}/Cargo.lock"; + }; + buildInputs = old.buildInputs ++ [ libcap_ng ]; # new dep +}) From e00609ce7360ca56ecc13b4ec401fef9c247bae5 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 27 Feb 2026 02:50:30 -0300 Subject: [PATCH 22/25] nix: add some camera/pw testing tools to testvm --- nixosModules/testvm.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nixosModules/testvm.nix b/nixosModules/testvm.nix index 466cff5..aaf30d3 100644 --- a/nixosModules/testvm.nix +++ b/nixosModules/testvm.nix @@ -35,5 +35,10 @@ pkgs.nautilus pkgs.rewaita pkgs.wl-clipboard-rs + pkgs.snapshot + pkgs.gst_all_1.gst-plugins-base + pkgs.gst_all_1.gst-plugins-good + pkgs.gst_all_1.gst-plugins-bad + pkgs.gst_all_1.gstreamer ]; } From 604ebc1356c204a267e230bd5090505e119d1814 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 27 Feb 2026 02:51:07 -0300 Subject: [PATCH 23/25] [BREAKING] Switch to virtgpu-based D-Bus tunneling This introduces support for drag&drop and printing portals, and later camera/screencasting should be possible as well. However we break backwards compatibility with already built closures because the nixosModule needs to be changed. In the next commit, the runtime environment related services will be removed from the nixosModule to prevent unnecessary future breakage. --- flake.lock | 14 +++++++------- flake.nix | 6 ++---- munix | 26 ++++++++++++++++++-------- nixosModules/default.nix | 7 +++---- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/flake.lock b/flake.lock index 84f1720..165ec30 100644 --- a/flake.lock +++ b/flake.lock @@ -40,17 +40,17 @@ "muvm-src": { "flake": false, "locked": { - "lastModified": 1769336998, - "narHash": "sha256-ZFtAYwr3AaD8WsDmXJ6eU12UojzfMm50UBWmWIXstl0=", + "lastModified": 1772176363, + "narHash": "sha256-aSWulv3ml4XmMYnFOkZCd2YBLIY0Rr8CUHK1NDYk5jw=", "owner": "valpackett", "repo": "muvm", - "rev": "ae7dbd49aac04e9732a14a424572e99a81eb1298", + "rev": "c68742bcedb96deb6f23ed5a83188022d1cdf71d", "type": "github" }, "original": { "owner": "valpackett", "repo": "muvm", - "rev": "ae7dbd49aac04e9732a14a424572e99a81eb1298", + "rev": "c68742bcedb96deb6f23ed5a83188022d1cdf71d", "type": "github" } }, @@ -89,10 +89,10 @@ ] }, "locked": { - "lastModified": 1770365107, - "narHash": "sha256-rp2hDKF3pwHN0lBr09ckMNaMSJnwNolQmiad8C7u41Q=", + "lastModified": 1772183103, + "narHash": "sha256-9jbqBtaLUdOeT95PVUMz45JdUpVeJ25ZYZHEOQn9XsI=", "ref": "main", - "rev": "26261306592f6173fb844083b396bebf8140cb2b", + "rev": "c42eaef55440e2594677ede5279bd8c3eaf128f2", "shallow": true, "type": "git", "url": "https://git.clan.lol/clan/sidebus" diff --git a/flake.nix b/flake.nix index 84c3166..e7904a2 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,7 @@ # To override with local checkouts during development, use the --override-input CLI flag! muvm-src = { - url = "github:valpackett/muvm/ae7dbd49aac04e9732a14a424572e99a81eb1298"; # v0.5.0+custom-init + url = "github:valpackett/muvm/c68742bcedb96deb6f23ed5a83188022d1cdf71d"; # v0.5.0+custom-init+dbus flake = false; }; libkrun-src = { @@ -49,7 +49,7 @@ flake = { nixosModules.testvm = nixpkgs.lib.modules.importApply ./nixosModules/testvm.nix { }; nixosModules.default = nixpkgs.lib.modules.importApply ./nixosModules/default.nix { - inherit self sidebus; + inherit self; }; templates.musictest = { @@ -124,8 +124,6 @@ sidebus-broker = sidebus.packages.${system}.sidebus-broker; }; - sidebus-agent = sidebus.packages.${system}.sidebus-agent; - wl-cross-domain-proxy = pkgs.callPackage ./packages/wl-cross-domain-proxy { }; }; diff --git a/munix b/munix index 4f26980..ecd7920 100755 --- a/munix +++ b/munix @@ -10,6 +10,7 @@ MICROVM_UID=1337 MICROVM_GID=1337 BWRAP_ARGS=() MUVM_ARGS=() +SIDEBUS_ARGS=() GPU=1 WAYLAND=1 PIPEWIRE=1 @@ -31,10 +32,10 @@ while [ "$#" -gt 0 ]; do --no-pipewire) PIPEWIRE=0; shift 1;; --no-env-defaults) ENV_DEFAULTS=0; shift 1;; --x11) X11=1; shift 1;; - -b|--bind) BWRAP_ARGS+=("--bind" "$2" "$3"); shift 3;; - --ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); shift 3;; - -e|--expose) BWRAP_ARGS+=("--bind" "$2" "$2"); shift 2;; - --ro-expose) BWRAP_ARGS+=("--ro-bind" "$2" "$2"); shift 2;; + -b|--bind) BWRAP_ARGS+=("--bind" "$2" "$3"); SIDEBUS_ARGS+=("--path-mapping" "$3=$2"); shift 3;; + --ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); SIDEBUS_ARGS+=("--path-mapping" "$3=$2"); shift 3;; + -e|--expose) BWRAP_ARGS+=("--bind" "$2" "$2"); SIDEBUS_ARGS+=("--path-mapping" "$2=$2"); shift 2;; + --ro-expose) BWRAP_ARGS+=("--ro-bind" "$2" "$2"); SIDEBUS_ARGS+=("--path-mapping" "$2=$2"); shift 2;; -p|--publish) USING_PUBLISH=1; MUVM_ARGS+=("--publish=$2"); shift 2;; --host-opengl-driver) HOST_OPENGL_DRIVER="$2"; shift 2;; --munix-bin-dir) SCRIPT_PATH="$2"; shift 2;; @@ -186,12 +187,20 @@ trap cleanup EXIT INT TERM HOST_RUNTIME_DIR="$XDG_RUNTIME_DIR/munix.$$" mkdir -p $HOST_RUNTIME_DIR rm $HOST_RUNTIME_DIR/* -sidebus-broker --guest-mountpoint /mnt/munix-doc-portal/doc --runtime-dir "$HOST_RUNTIME_DIR" --unix-path "$HOST_RUNTIME_DIR/port.sock" >/dev/null 2>&1 & +mkdir -p "$HOST_RUNTIME_DIR/home" +RUST_LOG=debug sidebus-broker \ + --path-mapping "/home=$HOST_RUNTIME_DIR/home" \ + "${SIDEBUS_ARGS[@]}" \ + --guest-mountpoint /mnt/munix-doc-portal/doc \ + --runtime-dir "$HOST_RUNTIME_DIR" \ + --unix-path "$HOST_RUNTIME_DIR/port.sock" & # >/dev/null 2>&1 & BG_PIDS+=("$!") while [ ! -S "$HOST_RUNTIME_DIR/port.sock" ]; do sleep 0.1; done -BWRAP_ARGS+=( +BWRAP_ARGS=( # prepend home mount before other mounts to not override custom bind mounts under /home + --bind "$HOST_RUNTIME_DIR/home" /home + "${BWRAP_ARGS[@]}" --bind "$HOST_RUNTIME_DIR" /mnt/munix-doc-portal - --bind "$HOST_RUNTIME_DIR/port.sock" "$XDG_RUNTIME_DIR/krun/socket/port-50000" + --setenv "RUTABAGA_DBUS_CLIENT_SOCKET" /mnt/munix-doc-portal/port.sock ) if [ "$ENV_DEFAULTS" -eq 1 ]; then MUVM_ARGS+=( @@ -221,6 +230,7 @@ bwrap --unshare-all --share-net \ --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-remote \ --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-configure-network \ --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-pwbridge \ + --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-dbusbridge \ --symlink "$MICROVM_CLOSURE/etc" /etc \ --symlink "$MICROVM_CLOSURE/sw/bin/sh" /bin/sh \ --symlink "$MICROVM_CLOSURE/sw/bin/env" /usr/bin/env \ @@ -232,7 +242,7 @@ bwrap --unshare-all --share-net \ --setenv PATH "/run/munix/muvm:/run/munix/passt:$MICROVM_CLOSURE/sw/bin" \ "${BWRAP_ARGS[@]}" \ muvm \ - --custom-init-cmdline "/opt/bin/micro-activate $MICROVM_CLOSURE/sw/sbin/init --log-target=console systemd.set_credential=sidebus.port:50000" \ + --custom-init-cmdline "/opt/bin/micro-activate $MICROVM_CLOSURE/sw/sbin/init --log-target=console" \ "${MUVM_ARGS[@]}" \ -e container=munix \ -e MICROVM_CLOSURE="$MICROVM_CLOSURE" \ diff --git a/nixosModules/default.nix b/nixosModules/default.nix index 15a5a08..e670144 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -1,6 +1,5 @@ { self, - sidebus, }: { pkgs, @@ -282,16 +281,16 @@ in Group = "appvm"; }; }; - systemd.services.sidebus-agent = { + systemd.services.session-bus-bridge = { enable = true; description = "D-Bus session bus"; wantedBy = ["microvm.target"]; requires = ["session-bus.socket" "session-bus.service"]; after = ["session-bus.service"]; serviceConfig = { - ImportCredential = "sidebus.port"; Environment = ["DBUS_SESSION_BUS_ADDRESS=unix:path=${runtimeDir}/dbus.sock"]; - ExecStart = "${sidebus.packages.${system}.sidebus-agent}/bin/sidebus-agent"; + ExecStartPre = "+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128"; + ExecStart = "/opt/bin/muvm-dbusbridge"; User = "appvm"; Group = "appvm"; }; From 38a96b79b36de600ec7ba2472a8b6e878dd4a29d Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 6 Mar 2026 04:53:30 -0300 Subject: [PATCH 24/25] [BREAKING] Provide runtime environment systemd services from munix These services evolve as munix evolves, so they should not be part of the system closures themselves. Mount them into /run/systemd instead. (Yes, making /run/systemd/system a symlink to RO files is unfortunate, that could be changed in the future. FS prep code is annoying too..) --- devShells/default.nix | 2 + flake.nix | 2 + micro-activate.rs | 2 + munix | 10 ++ nixosModules/default.nix | 109 ------------------ packages/munix/default.nix | 15 ++- .../muvm-configure-network.service | 1 + .../microvm.target.wants/muvm-remote.service | 1 + .../pipewire-bridge.socket | 1 + .../session-bus-bridge.service | 1 + .../wayland-bridge.socket | 1 + systemd/muvm-configure-network.service | 6 + systemd/muvm-remote.service | 33 ++++++ systemd/pipewire-bridge.service | 12 ++ systemd/pipewire-bridge.socket | 8 ++ systemd/session-bus-bridge.service | 11 ++ systemd/wayland-bridge.service | 13 +++ systemd/wayland-bridge.socket | 9 ++ 18 files changed, 125 insertions(+), 112 deletions(-) create mode 100644 systemd/microvm.target.wants/muvm-configure-network.service create mode 100644 systemd/microvm.target.wants/muvm-remote.service create mode 100644 systemd/microvm.target.wants/pipewire-bridge.socket create mode 100644 systemd/microvm.target.wants/session-bus-bridge.service create mode 100644 systemd/microvm.target.wants/wayland-bridge.socket create mode 100644 systemd/muvm-configure-network.service create mode 100644 systemd/muvm-remote.service create mode 100644 systemd/pipewire-bridge.service create mode 100644 systemd/pipewire-bridge.socket create mode 100644 systemd/session-bus-bridge.service create mode 100644 systemd/wayland-bridge.service create mode 100644 systemd/wayland-bridge.socket diff --git a/devShells/default.nix b/devShells/default.nix index 382eb7b..0798e86 100644 --- a/devShells/default.nix +++ b/devShells/default.nix @@ -10,6 +10,7 @@ libkrun, muvm, sidebus-broker, + wl-cross-domain-proxy, pkgs, }: @@ -32,6 +33,7 @@ mkShell { passt bubblewrap sidebus-broker + wl-cross-domain-proxy ] ++ (with pkgs; [ meson diff --git a/flake.nix b/flake.nix index e7904a2..cbc0887 100644 --- a/flake.nix +++ b/flake.nix @@ -121,6 +121,7 @@ munix = pkgs.callPackage ./packages/munix { mesa = self'.packages.mesa; muvm = self'.packages.muvm; + wl-cross-domain-proxy = self'.packages.wl-cross-domain-proxy; sidebus-broker = sidebus.packages.${system}.sidebus-broker; }; @@ -130,6 +131,7 @@ devShells.default = pkgs.callPackage ./devShells { libkrun = self'.packages.libkrun; muvm = self'.packages.muvm; + wl-cross-domain-proxy = self'.packages.wl-cross-domain-proxy; sidebus-broker = sidebus.packages.${system}.sidebus-broker; }; }; diff --git a/micro-activate.rs b/micro-activate.rs index 776dae4..765fb30 100644 --- a/micro-activate.rs +++ b/micro-activate.rs @@ -90,6 +90,8 @@ fn main() -> Result<(), std::io::Error> { std::fs::write("/run/localtime", &localtime)?; std::fs::write("/run/resolv.conf", &resolv_conf)?; std::fs::write("/run/machine-id", &gen_machine_id())?; + std::fs::create_dir("/run/systemd")?; + std::os::unix::fs::symlink("/opt/systemd", "/run/systemd/system")?; std::os::unix::fs::symlink(&closure, "/run/current-system")?; if let Ok(tmp_graphics) = std::fs::read(format!("{closure}/etc/tmpfiles.d/graphics-driver.conf")) diff --git a/munix b/munix index ecd7920..7fbd9b0 100755 --- a/munix +++ b/munix @@ -2,8 +2,10 @@ SCRIPT_PATH=$(dirname $(realpath -s $0)) MUVM_PATH=$(dirname $(which muvm)) PASST_PATH=$(dirname $(which passt)) +WL_PROXY_PATH=$(dirname $(which wl-cross-domain-proxy)) HOST_OPENGL_DRIVER=/run/opengl-driver : "${MICROVM_DEFAULT_COMMAND:=bash}" +: "${MUNIX_SYSTEMD_UNITS:="${SCRIPT_PATH}/systemd"}" MICROVM_CLOSURE= MICROVM_COMMAND=() MICROVM_UID=1337 @@ -41,6 +43,7 @@ while [ "$#" -gt 0 ]; do --munix-bin-dir) SCRIPT_PATH="$2"; shift 2;; --muvm-bin-dir) MUVM_PATH="$2"; shift 2;; --passt-bin-dir) PASST_PATH="$2"; shift 2;; + --wl-proxy-bin-dir) WL_PROXY_PATH="$2"; shift 2;; --) shift 1; MICROVM_COMMAND+=("$@"); break;; -*) echo "munix: unknown option: $1" >&2; exit 1;; *) @@ -68,6 +71,11 @@ if [ "$PASST_PATH" = "" ]; then exit 1 fi +if [ "$WL_PROXY_PATH" = "" ]; then + echo "munix: wl-cross-domain-proxy not found, provide a --wl-proxy-bin-dir or fix \$PATH" >&2 + exit 1 +fi + if [ ! -e "$HOST_OPENGL_DRIVER" ]; then echo "munix: host graphics driver not found, provide a --host-opengl-driver" >&2 exit 1 @@ -227,10 +235,12 @@ bwrap --unshare-all --share-net \ --ro-bind "$MUVM_PATH" /run/munix/muvm \ --ro-bind "$PASST_PATH" /run/munix/passt \ --ro-bind "$SCRIPT_PATH/micro-activate" /opt/bin/micro-activate \ + --ro-bind "$WL_PROXY_PATH/wl-cross-domain-proxy" /opt/bin/wl-cross-domain-proxy \ --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-remote \ --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-configure-network \ --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-pwbridge \ --ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-dbusbridge \ + --ro-bind "$MUNIX_SYSTEMD_UNITS" /opt/systemd \ --symlink "$MICROVM_CLOSURE/etc" /etc \ --symlink "$MICROVM_CLOSURE/sw/bin/sh" /bin/sh \ --symlink "$MICROVM_CLOSURE/sw/bin/env" /usr/bin/env \ diff --git a/nixosModules/default.nix b/nixosModules/default.nix index e670144..35398b8 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -9,12 +9,6 @@ ... }: let - useTTY = { - TTYPath = "/dev/hvc0"; - StandardOutput = "tty"; - StandardInput = "tty"; - StandardError = "tty"; - }; runtimeDir = "/run/vm-user"; system = pkgs.stdenv.hostPlatform.system; in @@ -171,95 +165,6 @@ in systemd.settings.Manager.DefaultEnvironment = "XDG_RUNTIME_DIR=${runtimeDir}"; - systemd.services.muvm-remote = { - enable = true; - description = "microVM Application runner"; - onFailure = [ "exit.target" ]; - onSuccess = [ "exit.target" ]; - wants = [ "sockets.target" ]; - after = [ "sockets.target" ]; - wantedBy = [ "microvm.target" ]; - serviceConfig = { - Type = "exec"; - PassEnvironment = [ - "MESA_LOADER_DRIVER_OVERRIDE" - "MUVM_REMOTE_CONFIG" - # "KRUN_CONFIG" - - "TERM" - "XDG_SESSION_TYPE" - "SDL_VIDEODRIVER" - "QT_QPA_PLATFORM" - "_JAVA_AWT_WM_NONREPARENTING" - "ELECTRON_OZONE_PLATFORM_HINT" - "GTK_USE_PORTAL" - "QT_QPA_PLATFORMTHEME" - ]; - Environment = [ - "WAYLAND_DISPLAY=wayland-1" - "DBUS_SESSION_BUS_ADDRESS=unix:path=${runtimeDir}/dbus.sock" - "PATH=/run/current-system/sw/bin" - ]; - User = "appvm"; - Group = "appvm"; - ExecStartPre = "+/run/current-system/sw/bin/chown appvm:appvm ${runtimeDir}"; - 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 = { - enable = true; - description = "Wayland cross-domain proxy socket"; - wantedBy = [ "microvm.target" ]; - partOf = [ "wayland-proxy.service" ]; - listenStreams = [ "${runtimeDir}/wayland-1" ]; - socketConfig = { - SocketUser = "appvm"; - SocketGroup = "appvm"; - FileDescriptorName = "wayland"; - }; - }; - systemd.services.wayland-proxy = { - enable = true; - description = "Wayland cross-domain proxy"; - requires = [ "wayland-proxy.socket" ]; - serviceConfig = { - ExecStartPre = "+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128"; - ExecStart = "${self.packages.${system}.wl-cross-domain-proxy}/bin/wl-cross-domain-proxy --listen-fd --filter-global wp_presentation"; - User = "appvm"; - Group = "appvm"; - }; - }; - systemd.sockets.session-bus = { enable = true; description = "D-Bus session bus socket"; @@ -281,20 +186,6 @@ in Group = "appvm"; }; }; - systemd.services.session-bus-bridge = { - enable = true; - description = "D-Bus session bus"; - wantedBy = ["microvm.target"]; - requires = ["session-bus.socket" "session-bus.service"]; - after = ["session-bus.service"]; - serviceConfig = { - Environment = ["DBUS_SESSION_BUS_ADDRESS=unix:path=${runtimeDir}/dbus.sock"]; - ExecStartPre = "+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128"; - ExecStart = "/opt/bin/muvm-dbusbridge"; - User = "appvm"; - Group = "appvm"; - }; - }; hardware.graphics.enable = true; hardware.graphics.package = self.packages.${system}.mesa; diff --git a/packages/munix/default.nix b/packages/munix/default.nix index ed82b9a..d7ff431 100644 --- a/packages/munix/default.nix +++ b/packages/munix/default.nix @@ -1,9 +1,18 @@ -{ stdenv, writeScriptBin, symlinkJoin, makeWrapper, muvm, passt, bubblewrap, sidebus-broker, mesa, rustc }: +{ stdenv, writeScriptBin, symlinkJoin, makeWrapper, muvm, passt, bubblewrap, sidebus-broker, wl-cross-domain-proxy, mesa, rustc }: let munixScript = (writeScriptBin "munix" (builtins.readFile ../../munix)).overrideAttrs(old: { buildCommand = "${old.buildCommand}\n patchShebangs $out"; }); + munixSystemd = stdenv.mkDerivation { + name = "munix-systemd"; + src = ../../systemd; + dontUnpack = true; + installPhase = '' + mkdir -p $out + cp -aR $src/* $out + ''; + }; microActivate = stdenv.mkDerivation { name = "micro-activate"; src = ../../micro-activate.rs; @@ -19,9 +28,9 @@ let }; in symlinkJoin { name = "munix"; - paths = [ munixScript microActivate muvm passt bubblewrap sidebus-broker ]; + paths = [ munixScript microActivate muvm passt bubblewrap sidebus-broker wl-cross-domain-proxy ]; buildInputs = [ makeWrapper ]; postBuild = '' - wrapProgram $out/bin/munix --prefix PATH : $out/bin --set FALLBACK_OPENGL_DRIVER ${mesa} + wrapProgram $out/bin/munix --prefix PATH : $out/bin --set FALLBACK_OPENGL_DRIVER ${mesa} --set MUNIX_SYSTEMD_UNITS ${munixSystemd} ''; } diff --git a/systemd/microvm.target.wants/muvm-configure-network.service b/systemd/microvm.target.wants/muvm-configure-network.service new file mode 100644 index 0000000..ca93c89 --- /dev/null +++ b/systemd/microvm.target.wants/muvm-configure-network.service @@ -0,0 +1 @@ +../muvm-configure-network.service \ No newline at end of file diff --git a/systemd/microvm.target.wants/muvm-remote.service b/systemd/microvm.target.wants/muvm-remote.service new file mode 100644 index 0000000..4f9f550 --- /dev/null +++ b/systemd/microvm.target.wants/muvm-remote.service @@ -0,0 +1 @@ +../muvm-remote.service \ No newline at end of file diff --git a/systemd/microvm.target.wants/pipewire-bridge.socket b/systemd/microvm.target.wants/pipewire-bridge.socket new file mode 100644 index 0000000..95e1850 --- /dev/null +++ b/systemd/microvm.target.wants/pipewire-bridge.socket @@ -0,0 +1 @@ +../pipewire-bridge.socket \ No newline at end of file diff --git a/systemd/microvm.target.wants/session-bus-bridge.service b/systemd/microvm.target.wants/session-bus-bridge.service new file mode 100644 index 0000000..faa559d --- /dev/null +++ b/systemd/microvm.target.wants/session-bus-bridge.service @@ -0,0 +1 @@ +../session-bus-bridge.service \ No newline at end of file diff --git a/systemd/microvm.target.wants/wayland-bridge.socket b/systemd/microvm.target.wants/wayland-bridge.socket new file mode 100644 index 0000000..4bcb084 --- /dev/null +++ b/systemd/microvm.target.wants/wayland-bridge.socket @@ -0,0 +1 @@ +../wayland-bridge.socket \ No newline at end of file diff --git a/systemd/muvm-configure-network.service b/systemd/muvm-configure-network.service new file mode 100644 index 0000000..3a67ff4 --- /dev/null +++ b/systemd/muvm-configure-network.service @@ -0,0 +1,6 @@ +[Unit] +Description=microVM Network configuration + +[Service] +Type=oneshot +ExecStart=/opt/bin/muvm-configure-network diff --git a/systemd/muvm-remote.service b/systemd/muvm-remote.service new file mode 100644 index 0000000..6164434 --- /dev/null +++ b/systemd/muvm-remote.service @@ -0,0 +1,33 @@ +[Unit] +After=sockets.target +Description=microVM Application runner +OnFailure=exit.target +OnSuccess=exit.target +Wants=sockets.target + +[Service] +Type=exec +# Environment="LOCALE_ARCHIVE=/nix/store/1hilqf0v1nm2w8xj87pwpm0rgq6lvhlv-glibc-locales-2.42-47/lib/locale/locale-archive" +# Environment="TZDIR=/nix/store/80izpiglrlqv2zb7rd7m5274k2dr142l-tzdata-2025c/share/zoneinfo" +Environment=WAYLAND_DISPLAY=wayland-1 +Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/vm-user/dbus.sock +Environment=PATH=/run/current-system/sw/bin +PassEnvironment=MESA_LOADER_DRIVER_OVERRIDE +PassEnvironment=MUVM_REMOTE_CONFIG +PassEnvironment=TERM +PassEnvironment=XDG_SESSION_TYPE +PassEnvironment=SDL_VIDEODRIVER +PassEnvironment=QT_QPA_PLATFORM +PassEnvironment=_JAVA_AWT_WM_NONREPARENTING +PassEnvironment=ELECTRON_OZONE_PLATFORM_HINT +PassEnvironment=GTK_USE_PORTAL +PassEnvironment=QT_QPA_PLATFORMTHEME +ExecStartPre=+/run/current-system/sw/bin/chown appvm:appvm /run/vm-user +ExecStart=/opt/bin/muvm-remote +ExecStopPost=+/nix/store/ygzfhw5nxrn7qqfqmz2s9p6cikcjqqkh-python3-3.13.11/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')))" +User=appvm +Group=appvm +StandardError=tty +StandardInput=tty +StandardOutput=tty +TTYPath=/dev/hvc0 diff --git a/systemd/pipewire-bridge.service b/systemd/pipewire-bridge.service new file mode 100644 index 0000000..25c53e2 --- /dev/null +++ b/systemd/pipewire-bridge.service @@ -0,0 +1,12 @@ +[Unit] +Description=PipeWire VM bridge +Requires=pipewire-bridge.socket + +[Service] +Type=exec +ExecStart=/opt/bin/muvm-pwbridge + +# Environment=RUST_LOG=debug +# StandardError=tty +# StandardOutput=tty +# TTYPath=/dev/hvc0 diff --git a/systemd/pipewire-bridge.socket b/systemd/pipewire-bridge.socket new file mode 100644 index 0000000..998e661 --- /dev/null +++ b/systemd/pipewire-bridge.socket @@ -0,0 +1,8 @@ +[Unit] +Description=PipeWire VM bridge socket +PartOf=pipewire-bridge.service + +[Socket] +SocketGroup=appvm +SocketUser=appvm +ListenStream=/run/vm-user/pipewire-0 diff --git a/systemd/session-bus-bridge.service b/systemd/session-bus-bridge.service new file mode 100644 index 0000000..9b12a85 --- /dev/null +++ b/systemd/session-bus-bridge.service @@ -0,0 +1,11 @@ +[Unit] +After=session-bus.service +Description=D-Bus VM integration bridge +Requires=session-bus.socket session-bus.service + +[Service] +Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/vm-user/dbus.sock +ExecStartPre=+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128 +ExecStart=/opt/bin/muvm-dbusbridge +Group=appvm +User=appvm diff --git a/systemd/wayland-bridge.service b/systemd/wayland-bridge.service new file mode 100644 index 0000000..c74ba4e --- /dev/null +++ b/systemd/wayland-bridge.service @@ -0,0 +1,13 @@ +[Unit] +Description=Wayland VM bridge +Requires=wayland-bridge.socket + +[Service] +ExecStartPre=+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128 +ExecStart=/opt/bin/wl-cross-domain-proxy --listen-fd --filter-global wp_presentation +User=appvm +Group=appvm + +StandardError=tty +StandardOutput=tty +TTYPath=/dev/hvc0 diff --git a/systemd/wayland-bridge.socket b/systemd/wayland-bridge.socket new file mode 100644 index 0000000..2706a2b --- /dev/null +++ b/systemd/wayland-bridge.socket @@ -0,0 +1,9 @@ +[Unit] +Description=Wayland VM bridge socket +PartOf=wayland-bridge.service + +[Socket] +FileDescriptorName=wayland +SocketGroup=appvm +SocketUser=appvm +ListenStream=/run/vm-user/wayland-1 From a7fe813f1776e546ec505f5e89ae36174b42f377 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 6 Mar 2026 05:55:47 -0300 Subject: [PATCH 25/25] Add wl-backdrop (WIP) --bg-color option --- devShells/default.nix | 2 ++ flake.lock | 28 +++++++++++++++++++++++++++- flake.nix | 7 +++++++ munix | 23 +++++++++++++++++++++++ packages/munix/default.nix | 4 ++-- 5 files changed, 61 insertions(+), 3 deletions(-) diff --git a/devShells/default.nix b/devShells/default.nix index 0798e86..c288f30 100644 --- a/devShells/default.nix +++ b/devShells/default.nix @@ -11,6 +11,7 @@ muvm, sidebus-broker, wl-cross-domain-proxy, + wl-backdrop, pkgs, }: @@ -34,6 +35,7 @@ mkShell { bubblewrap sidebus-broker wl-cross-domain-proxy + wl-backdrop ] ++ (with pkgs; [ meson diff --git a/flake.lock b/flake.lock index 165ec30..234a180 100644 --- a/flake.lock +++ b/flake.lock @@ -76,7 +76,8 @@ "libkrun-src": "libkrun-src", "muvm-src": "muvm-src", "nixpkgs": "nixpkgs", - "sidebus": "sidebus" + "sidebus": "sidebus", + "wl-backdrop": "wl-backdrop" } }, "sidebus": { @@ -103,6 +104,31 @@ "type": "git", "url": "https://git.clan.lol/clan/sidebus" } + }, + "wl-backdrop": { + "inputs": { + "flake-parts": [ + "flake-parts" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772781884, + "narHash": "sha256-epVLmAHnJi4EoZea5DUmxB3r6SPSMu3Nzki7JzbK0sA=", + "ref": "main", + "rev": "20e3910ef60aa627933a5d750b60cc3dcd0653cf", + "shallow": true, + "type": "git", + "url": "https://git.clan.lol/valpackett/wl-backdrop" + }, + "original": { + "ref": "main", + "shallow": true, + "type": "git", + "url": "https://git.clan.lol/valpackett/wl-backdrop" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index cbc0887..6b9191b 100644 --- a/flake.nix +++ b/flake.nix @@ -14,6 +14,10 @@ sidebus.inputs.nixpkgs.follows = "nixpkgs"; sidebus.inputs.flake-parts.follows = "flake-parts"; + wl-backdrop.url = "git+https://git.clan.lol/valpackett/wl-backdrop?shallow=1&ref=main"; + wl-backdrop.inputs.nixpkgs.follows = "nixpkgs"; + wl-backdrop.inputs.flake-parts.follows = "flake-parts"; + # To override with local checkouts during development, use the --override-input CLI flag! muvm-src = { url = "github:valpackett/muvm/c68742bcedb96deb6f23ed5a83188022d1cdf71d"; # v0.5.0+custom-init+dbus @@ -35,6 +39,7 @@ nixpkgs, flake-parts, sidebus, + wl-backdrop, muvm-src, libkrun-src, # libkrunfw-src, @@ -122,6 +127,7 @@ mesa = self'.packages.mesa; muvm = self'.packages.muvm; wl-cross-domain-proxy = self'.packages.wl-cross-domain-proxy; + wl-backdrop = wl-backdrop.packages.${system}.wl-backdrop; sidebus-broker = sidebus.packages.${system}.sidebus-broker; }; @@ -132,6 +138,7 @@ libkrun = self'.packages.libkrun; muvm = self'.packages.muvm; wl-cross-domain-proxy = self'.packages.wl-cross-domain-proxy; + wl-backdrop = wl-backdrop.packages.${system}.wl-backdrop; sidebus-broker = sidebus.packages.${system}.sidebus-broker; }; }; diff --git a/munix b/munix index 7fbd9b0..619a38f 100755 --- a/munix +++ b/munix @@ -3,6 +3,7 @@ SCRIPT_PATH=$(dirname $(realpath -s $0)) MUVM_PATH=$(dirname $(which muvm)) PASST_PATH=$(dirname $(which passt)) WL_PROXY_PATH=$(dirname $(which wl-cross-domain-proxy)) +WL_BACKDROP_PATH=$(dirname $(which wl-backdrop)) HOST_OPENGL_DRIVER=/run/opengl-driver : "${MICROVM_DEFAULT_COMMAND:=bash}" : "${MUNIX_SYSTEMD_UNITS:="${SCRIPT_PATH}/systemd"}" @@ -25,6 +26,22 @@ if [ ! -e "$HOST_OPENGL_DRIVER" ]; then HOST_OPENGL_DRIVER="$FALLBACK_OPENGL_DRIVER" fi +# A little bit cursed: pre-pass to relaunch with new env var.. +BG_COLOR= +pargs=() +while [ "$#" -gt 0 ]; do + case "$1" in + --bg-color) BG_COLOR="$2"; shift 2;; + --wl-backdrop-bin-dir) WL_BACKDROP_PATH="$2"; shift 2;; + *) pargs+=("$1"); shift;; + esac +done +if [ "$BG_COLOR" = "" ]; then + set -- "${pargs[@]}" +else + exec "$WL_BACKDROP_PATH/wl-backdrop" --background "$BG_COLOR" -- "$(readlink -f "$0")" "${pargs[@]}" +fi + while [ "$#" -gt 0 ]; do case "$1" in -u|--uid) MICROVM_UID="$2"; shift 2;; @@ -44,6 +61,7 @@ while [ "$#" -gt 0 ]; do --muvm-bin-dir) MUVM_PATH="$2"; shift 2;; --passt-bin-dir) PASST_PATH="$2"; shift 2;; --wl-proxy-bin-dir) WL_PROXY_PATH="$2"; shift 2;; + --wl-backdrop-bin-dir) shift 2;; --) shift 1; MICROVM_COMMAND+=("$@"); break;; -*) echo "munix: unknown option: $1" >&2; exit 1;; *) @@ -76,6 +94,11 @@ if [ "$WL_PROXY_PATH" = "" ]; then exit 1 fi +if [ "$WL_BACKDROP_PATH" = "" ]; then + echo "munix: wl-backdrop not found, provide a --wl-backdrop-bin-dir or fix \$PATH" >&2 + exit 1 +fi + if [ ! -e "$HOST_OPENGL_DRIVER" ]; then echo "munix: host graphics driver not found, provide a --host-opengl-driver" >&2 exit 1 diff --git a/packages/munix/default.nix b/packages/munix/default.nix index d7ff431..e0b848e 100644 --- a/packages/munix/default.nix +++ b/packages/munix/default.nix @@ -1,4 +1,4 @@ -{ stdenv, writeScriptBin, symlinkJoin, makeWrapper, muvm, passt, bubblewrap, sidebus-broker, wl-cross-domain-proxy, mesa, rustc }: +{ stdenv, writeScriptBin, symlinkJoin, makeWrapper, muvm, passt, bubblewrap, sidebus-broker, wl-cross-domain-proxy, wl-backdrop, mesa, rustc }: let munixScript = (writeScriptBin "munix" (builtins.readFile ../../munix)).overrideAttrs(old: { @@ -28,7 +28,7 @@ let }; in symlinkJoin { name = "munix"; - paths = [ munixScript microActivate muvm passt bubblewrap sidebus-broker wl-cross-domain-proxy ]; + paths = [ munixScript microActivate muvm passt bubblewrap sidebus-broker wl-cross-domain-proxy wl-backdrop ]; buildInputs = [ makeWrapper ]; postBuild = '' wrapProgram $out/bin/munix --prefix PATH : $out/bin --set FALLBACK_OPENGL_DRIVER ${mesa} --set MUNIX_SYSTEMD_UNITS ${munixSystemd}