Compare commits

...
Sign in to create a new pull request.

25 commits

Author SHA1 Message Date
Val Packett
a7fe813f17 Add wl-backdrop (WIP) --bg-color option 2026-03-06 06:45:39 -03:00
Val Packett
38a96b79b3 [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..)
2026-03-06 06:09:48 -03:00
Val Packett
604ebc1356 [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.
2026-03-06 05:09:55 -03:00
Val Packett
e00609ce73 nix: add some camera/pw testing tools to testvm 2026-02-27 02:50:54 -03:00
Val Packett
beeb5f5d9f Fork libkrun again to fix buffer mapping permission issue (fix #18)
Initial D-Bus WIP is also there..
2026-02-27 02:48:17 -03:00
zimbatm
adf2d24b60 fix(template): use structured settings for MPD audio output
Replace deprecated extraConfig with settings.audio_output
2026-02-24 11:08:53 +01:00
Val Packett
981393443b Set up a monotonic clock boot time offset in the VM 2026-02-20 05:17:13 -03:00
Val Packett
8c3878f117 Pass timezone through to the VM
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:<pipewireclock0> internal time 1:01:04.622699903
gstclock.c:1129:gst_clock_get_time:<pipewireclock0> 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
2026-02-20 04:19:18 -03:00
Val Packett
322b6efc1c nix: testvm: update stateVersion, add rewaita (theme coloring for demos) 2026-02-13 14:55:42 -03:00
Val Packett
820fcd3da1 nix: chase removal of etc overlay symlinks, fixes #14 2026-02-13 14:55:09 -03:00
Val Packett
53f827553f nix: add nautilus to testvm
Will be useful for testing drag-out
2026-02-07 01:24:55 -03:00
Val Packett
09f1eb76de 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.
2026-02-07 01:24:44 -03:00
Val Packett
9708e5fb64 nix: update nixpkgs
now includes the most recent libkrun(fw) releases
2026-02-07 00:21:19 -03:00
Val Packett
67666b8f46 nix: update sidebus and flake-parts
sidebus now uses flake-parts too
2026-02-07 00:17:26 -03:00
Val Packett
585970fe92 munix: do not set display from the script
It is now entirely managed by systemd.
2026-01-30 06:12:35 -03:00
Val Packett
a82b0de310 munix: set wayland/pw/portal enablement variables for toolkits by default 2026-01-30 06:10:48 -03:00
Val Packett
8113c269cb munix: add more arg shorthands 2026-01-30 05:47:22 -03:00
Val Packett
38213f4ada munix: add publish argument for port forwarding, fix #11
TODO: fix https://github.com/AsahiLinux/muvm/issues/178 as well
2026-01-30 05:44:13 -03:00
Val Packett
425ff896c8 nix: deorbit virtwl-proxy 2026-01-30 04:35:20 -03:00
Val Packett
9911b15fb7 nix: switch to wl-cross-domain-proxy 2026-01-30 04:27:22 -03:00
Val Packett
13b2afcc14 nix: add package for wl-cross-domain-proxy 2026-01-30 03:16:39 -03:00
Val Packett
c89c9e4d9b nix: testvm: more test apps 2026-01-30 03:15:49 -03:00
Val Packett
40d82a0fd8 nix: use static userborn
as it's upstream now
2026-01-30 01:39:17 -03:00
Val Packett
c11c6c6292 nix: update inputs 2026-01-30 00:02:31 -03:00
Val Packett
447ccad362 nix: devShell: add packages for proxy development 2026-01-29 20:54:07 -03:00
24 changed files with 441 additions and 366 deletions

View file

@ -1,17 +1,49 @@
{ 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,
wl-cross-domain-proxy,
wl-backdrop,
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
wl-cross-domain-proxy
wl-backdrop
]
++ (with pkgs; [
meson
wayland
wayland-protocols
wayland-scanner
cairo
libgbm
]);
# Enough things to compile wl-cross-domain-proxy, muvm, etc. in development
}

206
flake.lock generated
View file

@ -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,100 +20,47 @@
"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"
}
},
"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": {
"lastModified": 1764837222,
"narHash": "sha256-Q4uFc3gvo6AuN1fAuUWU8k/+idOuDEj8Pkhm80wE798=",
"owner": "containers",
"lastModified": 1772170018,
"narHash": "sha256-pi4Mrx9wFE8zT8lx+0su2bP1tTkJBh5FaGNQjAFUAx4=",
"owner": "valpackett",
"repo": "libkrun",
"rev": "b250ee6fff7d959da3d55bb62ffe09d87248651c",
"rev": "eeafbc55379b60379414168e7a22d5f95b73d7a0",
"type": "github"
},
"original": {
"owner": "containers",
"owner": "valpackett",
"repo": "libkrun",
"rev": "b250ee6fff7d959da3d55bb62ffe09d87248651c",
"type": "github"
}
},
"libkrunfw-src": {
"flake": false,
"locked": {
"lastModified": 1762790667,
"narHash": "sha256-tVQ0jGef8uJNo2L4Pmhy3ajVRKJ2Gs9oi44eOYAnmds=",
"owner": "containers",
"repo": "libkrunfw",
"rev": "8a8c33f24f72aa6ca017347dc2be45b6fa612af5",
"type": "github"
},
"original": {
"owner": "containers",
"repo": "libkrunfw",
"rev": "8a8c33f24f72aa6ca017347dc2be45b6fa612af5",
"rev": "eeafbc55379b60379414168e7a22d5f95b73d7a0",
"type": "github"
}
},
"muvm-src": {
"flake": false,
"locked": {
"lastModified": 1763708092,
"narHash": "sha256-8K9XDnQbl/fh1Bsx1SwFuo5WVy5BztCjMPT6NW01lXQ=",
"lastModified": 1772176363,
"narHash": "sha256-aSWulv3ml4XmMYnFOkZCd2YBLIY0Rr8CUHK1NDYk5jw=",
"owner": "valpackett",
"repo": "muvm",
"rev": "3ec4c90bbfb6d0111f91b898a7f17deb562f4f92",
"rev": "c68742bcedb96deb6f23ed5a83188022d1cdf71d",
"type": "github"
},
"original": {
"owner": "valpackett",
"repo": "muvm",
"rev": "3ec4c90bbfb6d0111f91b898a7f17deb562f4f92",
"rev": "c68742bcedb96deb6f23ed5a83188022d1cdf71d",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1764242076,
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
"lastModified": 1770197578,
"narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4",
"rev": "00c21e4c93d963c50d4c0c89bfa84ed6e0694df2",
"type": "github"
},
"original": {
@ -127,111 +74,60 @@
"inputs": {
"flake-parts": "flake-parts",
"libkrun-src": "libkrun-src",
"libkrunfw-src": "libkrunfw-src",
"muvm-src": "muvm-src",
"nixpkgs": "nixpkgs",
"sidebus": "sidebus",
"virtwl": "virtwl"
}
},
"rust-overlay": {
"inputs": {
"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"
"wl-backdrop": "wl-backdrop"
}
},
"sidebus": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
"flake-parts": [
"flake-parts"
],
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1765527875,
"narHash": "sha256-QKsl+TAjdd1qk8Nd9mlByz07S+kGi8voSxxTdUNjt6A=",
"ref": "main",
"rev": "c9095421c6ec33e7293879d2df9d050991200803",
"shallow": true,
"type": "git",
"url": "https://git.clan.lol/clan/sidebus"
},
"original": {
"ref": "main",
"shallow": true,
"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"
}
},
"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",
"lastModified": 1772183103,
"narHash": "sha256-9jbqBtaLUdOeT95PVUMz45JdUpVeJ25ZYZHEOQn9XsI=",
"ref": "main",
"rev": "c42eaef55440e2594677ede5279bd8c3eaf128f2",
"shallow": true,
"submodules": true,
"type": "git",
"url": "https://github.com/valpackett/wayland-proxy-virtwl"
"url": "https://git.clan.lol/clan/sidebus"
},
"original": {
"ref": "wip",
"ref": "main",
"shallow": true,
"submodules": true,
"type": "git",
"url": "https://github.com/valpackett/wayland-proxy-virtwl"
"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"
}
}
},

View file

@ -10,25 +10,27 @@
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";
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/3ec4c90bbfb6d0111f91b898a7f17deb562f4f92";
url = "github:valpackett/muvm/c68742bcedb96deb6f23ed5a83188022d1cdf71d"; # v0.5.0+custom-init+dbus
flake = false;
};
libkrun-src = {
url = "github:containers/libkrun/b250ee6fff7d959da3d55bb62ffe09d87248651c";
flake = false;
};
libkrunfw-src = {
url = "github:containers/libkrunfw/8a8c33f24f72aa6ca017347dc2be45b6fa612af5";
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;
# };
};
outputs =
@ -36,11 +38,11 @@
self,
nixpkgs,
flake-parts,
virtwl,
sidebus,
wl-backdrop,
muvm-src,
libkrun-src,
libkrunfw-src,
# libkrunfw-src,
...
}:
flake-parts.lib.mkFlake { inherit inputs; } {
@ -50,9 +52,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;
};
templates.musictest = {
@ -106,7 +108,7 @@
# 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 {
@ -124,15 +126,19 @@
munix = pkgs.callPackage ./packages/munix {
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;
};
sidebus-agent = sidebus.packages.${system}.sidebus-agent;
wl-cross-domain-proxy = pkgs.callPackage ./packages/wl-cross-domain-proxy { };
};
devShells.default = pkgs.callPackage ./devShells {
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;
};
};

View file

@ -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 {
@ -71,6 +74,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,8 +87,11 @@ 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::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"))
@ -131,6 +138,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())

97
munix
View file

@ -2,24 +2,46 @@
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"}"
MICROVM_CLOSURE=
MICROVM_COMMAND=()
MICROVM_UID=1337
MICROVM_GID=1337
BWRAP_ARGS=()
MUVM_ARGS=()
SIDEBUS_ARGS=()
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
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;;
@ -27,15 +49,19 @@ 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;;
--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;;
--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;;
--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;;
*)
@ -63,6 +89,16 @@ 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 [ "$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
@ -122,7 +158,15 @@ 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"
"-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
@ -140,6 +184,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
@ -169,13 +218,35 @@ 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+=(
"-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
fi
# xxx: some time is lost to the starting process..
[[ "$(</proc/uptime)" =~ ([0-9]+)\.([0-9]+) ]]
BOOT_TIME_OFFSET="${BASH_REMATCH[1]} $(( ${BASH_REMATCH[2]} * 1000000 ))"
# do not 'exec' because of cleanup :)
bwrap --unshare-all --share-net \
@ -187,23 +258,29 @@ 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 \
--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[@]}" \
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" \
-e MICROVM_UID="$MICROVM_UID" -e MICROVM_GID="$MICROVM_GID" \
-e BOOT_TIME_OFFSET="$BOOT_TIME_OFFSET" \
-i -t -- "${MICROVM_COMMAND[@]}" \
13< /etc/resolv.conf
13< /etc/resolv.conf \
14< /etc/localtime

View file

@ -1,7 +1,5 @@
{
self,
virtwl,
sidebus,
}:
{
pkgs,
@ -11,38 +9,7 @@
...
}:
let
useTTY = {
TTYPath = "/dev/hvc0";
StandardOutput = "tty";
StandardInput = "tty";
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
{
@ -79,12 +46,18 @@ 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 [ ];
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";
@ -166,23 +139,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;
@ -206,86 +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 = [
"TERM"
"MESA_LOADER_DRIVER_OVERRIDE"
"MUVM_REMOTE_CONFIG"
]; # "KRUN_CONFIG"];
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-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";
requires = [ "wayland-proxy-virtwl.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";
User = "appvm";
Group = "appvm";
};
};
systemd.sockets.session-bus = {
enable = true;
description = "D-Bus session bus socket";
@ -307,20 +186,6 @@ in
Group = "appvm";
};
};
systemd.services.sidebus-agent = {
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";
User = "appvm";
Group = "appvm";
};
};
hardware.graphics.enable = true;
hardware.graphics.package = self.packages.${system}.mesa;

View file

@ -1,13 +1,12 @@
{ virtwl }:
{ }:
{ pkgs, ... }: {
system.stateVersion = "25.11";
system.stateVersion = "26.05";
fonts.packages = [ pkgs.adwaita-fonts pkgs.dejavu_fonts ];
programs.dconf.enable = true;
environment.systemPackages = [
pkgs.fastfetch
pkgs.htop
virtwl.packages.${pkgs.stdenv.hostPlatform.system}.proxy
pkgs.wayland-utils
pkgs.weston
pkgs.waycheck
@ -16,8 +15,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 +32,13 @@
pkgs.zerotierone
pkgs.localsend
pkgs.ashpd-demo
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
];
}

View file

@ -1,18 +1,32 @@
{ libkrun, libkrunfw, libkrun-src, rustPlatform, variant ? null, ... }:
{
libkrun,
libkrunfw,
libkrun-src,
rustPlatform,
libcap_ng,
variant ? null,
...
}:
let
libkrunfw' = libkrunfw.override { inherit variant; };
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.override {
withBlk = true;
withGpu = true;
withSound = true;
withNet = true;
inherit variant;
libkrunfw = libkrunfw';
}).overrideAttrs (old: {
# libkrun'
libkrun'.overrideAttrs (old: {
src = libkrun-src;
cargoDeps = rustPlatform.importCargoLock {
lockFile = "${libkrun-src}/Cargo.lock";
};
buildInputs = old.buildInputs ++ [ libcap_ng ]; # new dep
})

View file

@ -1,12 +1,22 @@
{ libkrunfw, libkrunfw-src, fetchurl, variant ? null, ... }:
{
libkrunfw,
# libkrunfw-src,
# fetchurl,
variant ? null,
...
}:
(libkrunfw.override {
inherit variant;
}).overrideAttrs (old: {
version = "5.0.0";
src = libkrunfw-src;
kernelSrc = fetchurl {
url = "mirror://kernel/linux/kernel/v6.x/linux-6.12.44.tar.xz";
hash = "sha256-tlAhDtMCeyJJadFIqjd0Uqmq065/KFGr7dMa3+8Wva4=";
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=";
# };
# })

View file

@ -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, wl-backdrop, 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 wl-backdrop ];
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}
'';
}

View file

@ -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 ];
};
}

View file

@ -0,0 +1 @@
../muvm-configure-network.service

View file

@ -0,0 +1 @@
../muvm-remote.service

View file

@ -0,0 +1 @@
../pipewire-bridge.socket

View file

@ -0,0 +1 @@
../session-bus-bridge.service

View file

@ -0,0 +1 @@
../wayland-bridge.socket

View file

@ -0,0 +1,6 @@
[Unit]
Description=microVM Network configuration
[Service]
Type=oneshot
ExecStart=/opt/bin/muvm-configure-network

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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