nixos: add munix.defaultCommand option and system.build.munix
Add a NixOS option to configure the default command for the VM and provide a system.build.munix output that wraps munix with the correct toplevel and default command. This reduces boilerplate in downstream flakes since they no longer need to manually wrap munix. The template now uses these new features, significantly simplifying the apps definition.
This commit is contained in:
parent
2d721419e6
commit
ced0559be8
2 changed files with 317 additions and 275 deletions
|
|
@ -1,5 +1,16 @@
|
||||||
{ self, virtwl, sidebus }:
|
{
|
||||||
{ pkgs, lib, utils, config, ... }: let
|
self,
|
||||||
|
virtwl,
|
||||||
|
sidebus,
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
utils,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
useTTY = {
|
useTTY = {
|
||||||
TTYPath = "/dev/hvc0";
|
TTYPath = "/dev/hvc0";
|
||||||
StandardOutput = "tty";
|
StandardOutput = "tty";
|
||||||
|
|
@ -7,265 +18,315 @@
|
||||||
StandardError = "tty";
|
StandardError = "tty";
|
||||||
};
|
};
|
||||||
runtimeDir = "/run/vm-user";
|
runtimeDir = "/run/vm-user";
|
||||||
userbornConfig = {
|
userbornConfig = {
|
||||||
groups = lib.mapAttrsToList (username: opts: {
|
groups = lib.mapAttrsToList (username: opts: {
|
||||||
inherit (opts) name gid members;
|
inherit (opts) name gid members;
|
||||||
}) config.users.groups;
|
}) config.users.groups;
|
||||||
users = lib.mapAttrsToList (username: opts: {
|
users = lib.mapAttrsToList (username: opts: {
|
||||||
inherit (opts)
|
inherit (opts)
|
||||||
name
|
name
|
||||||
uid
|
uid
|
||||||
group
|
group
|
||||||
description
|
description
|
||||||
home
|
home
|
||||||
password
|
password
|
||||||
hashedPassword
|
hashedPassword
|
||||||
hashedPasswordFile
|
hashedPasswordFile
|
||||||
initialPassword
|
initialPassword
|
||||||
initialHashedPassword
|
initialHashedPassword
|
||||||
;
|
;
|
||||||
isNormal = opts.isNormalUser;
|
isNormal = opts.isNormalUser;
|
||||||
shell = utils.toShellPath opts.shell;
|
shell = utils.toShellPath opts.shell;
|
||||||
}) (lib.filterAttrs (_: u: u.enable) config.users.users);
|
}) (lib.filterAttrs (_: u: u.enable) config.users.users);
|
||||||
};
|
};
|
||||||
userbornConfigJson = pkgs.writeText "userborn.json" (builtins.toJSON userbornConfig);
|
userbornConfigJson = pkgs.writeText "userborn.json" (builtins.toJSON userbornConfig);
|
||||||
userbornResults = pkgs.runCommand "baked userborn" {} "mkdir -p $out; ${lib.getExe pkgs.userborn} ${userbornConfigJson} $out";
|
userbornResults =
|
||||||
|
pkgs.runCommand "baked userborn" { }
|
||||||
|
"mkdir -p $out; ${lib.getExe pkgs.userborn} ${userbornConfigJson} $out";
|
||||||
system = pkgs.stdenv.hostPlatform.system;
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
in {
|
in
|
||||||
boot.isContainer = true;
|
{
|
||||||
fileSystems."/".device = lib.mkDefault "/dev/sda"; # dummy
|
options.virtualisation.munix.defaultCommand = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
# Disable unused things
|
default = "bash";
|
||||||
environment.defaultPackages = lib.mkDefault [ ];
|
description = "Default command to run when starting the VM without arguments.";
|
||||||
documentation = {
|
|
||||||
enable = lib.mkDefault false;
|
|
||||||
doc.enable = lib.mkDefault false;
|
|
||||||
info.enable = lib.mkDefault false;
|
|
||||||
man.enable = lib.mkDefault false;
|
|
||||||
nixos.enable = lib.mkDefault false;
|
|
||||||
};
|
};
|
||||||
services.logrotate.enable = false;
|
|
||||||
services.udisks2.enable = false;
|
|
||||||
system.tools.nixos-generate-config.enable = false;
|
|
||||||
system.activationScripts.specialfs = lib.mkForce "";
|
|
||||||
systemd.coredump.enable = false;
|
|
||||||
networking.firewall.enable = false;
|
|
||||||
powerManagement.enable = false;
|
|
||||||
boot.kexec.enable = false;
|
|
||||||
console.enable = false;
|
|
||||||
|
|
||||||
# Configure activation / systemd
|
config = {
|
||||||
boot.initrd.systemd.enable = true; # for etc.overlay, but we don't have initrd
|
boot.isContainer = true;
|
||||||
system.etc.overlay.enable = true; # erofs
|
fileSystems."/".device = lib.mkDefault "/dev/sda"; # dummy
|
||||||
system.etc.overlay.mutable = false;
|
|
||||||
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."systemd/system".source = lib.mkForce (utils.systemdUtils.lib.generateUnits {
|
|
||||||
type = "system";
|
|
||||||
units = config.systemd.units;
|
|
||||||
upstreamUnits = [
|
|
||||||
"sysinit.target"
|
|
||||||
"local-fs.target"
|
|
||||||
"nss-user-lookup.target"
|
|
||||||
"umount.target"
|
|
||||||
"sockets.target"
|
|
||||||
"shutdown.target"
|
|
||||||
"reboot.target"
|
|
||||||
"exit.target"
|
|
||||||
"final.target"
|
|
||||||
"systemd-exit.service"
|
|
||||||
"systemd-journald.socket"
|
|
||||||
"systemd-journald-audit.socket"
|
|
||||||
"systemd-journald-dev-log.socket"
|
|
||||||
"systemd-journald.service"
|
|
||||||
"systemd-udevd-kernel.socket"
|
|
||||||
"systemd-udevd-control.socket"
|
|
||||||
"user.slice"
|
|
||||||
];
|
|
||||||
upstreamWants = ["multi-user.target.wants"];
|
|
||||||
});
|
|
||||||
|
|
||||||
# systemd.package = pkgs.systemdMinimal; # no analyze
|
# Disable unused things
|
||||||
systemd.defaultUnit = "microvm.target";
|
environment.defaultPackages = lib.mkDefault [ ];
|
||||||
systemd.targets.microvm = {
|
documentation = {
|
||||||
description = "Minimal microVM system";
|
enable = lib.mkDefault false;
|
||||||
wants = ["systemd-journald.socket" "systemd-udevd.service" "dbus.socket"];
|
doc.enable = lib.mkDefault false;
|
||||||
unitConfig.AllowIsolate = "yes";
|
info.enable = lib.mkDefault false;
|
||||||
};
|
man.enable = lib.mkDefault false;
|
||||||
systemd.services.generate-shutdown-ramfs.enable = lib.mkForce false;
|
nixos.enable = lib.mkDefault false;
|
||||||
systemd.services.systemd-remount-fs.enable = lib.mkForce false;
|
|
||||||
systemd.services.systemd-pstore.enable = lib.mkForce false;
|
|
||||||
systemd.services.lastlog2-import.enable = lib.mkForce false;
|
|
||||||
systemd.services.suid-sgid-wrappers.enable = lib.mkForce false;
|
|
||||||
systemd.services.systemd-udevd = {
|
|
||||||
# Redefine to remove the Before deps and get out of the critical chain
|
|
||||||
enable = true;
|
|
||||||
description = "Rule-based Manager for Device Events and Files";
|
|
||||||
unitConfig.DefaultDependencies = "no";
|
|
||||||
serviceConfig = {
|
|
||||||
CapabilityBoundingSet = "~CAP_SYS_TIME CAP_WAKE_ALARM";
|
|
||||||
Delegate = "";
|
|
||||||
DelegateSubgroup = "udev";
|
|
||||||
Type = "notify-reload";
|
|
||||||
OOMScoreAdjust = "-1000";
|
|
||||||
Sockets = "systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket";
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = "0";
|
|
||||||
ExecStart = "${pkgs.systemd}/lib/systemd/systemd-udevd";
|
|
||||||
FileDescriptorStoreMax = "512";
|
|
||||||
FileDescriptorStorePreserve = "yes";
|
|
||||||
KillMode = "mixed";
|
|
||||||
TasksMax = "infinity";
|
|
||||||
PrivateMounts = "yes";
|
|
||||||
ProtectHostname = "yes";
|
|
||||||
MemoryDenyWriteExecute = "yes";
|
|
||||||
RestrictAddressFamilies = "AF_UNIX AF_NETLINK AF_INET AF_INET6";
|
|
||||||
RestrictRealtime = "yes";
|
|
||||||
RestrictSUIDSGID = "yes";
|
|
||||||
SystemCallFilter = ["@system-service @module @raw-io bpf" "~@clock"];
|
|
||||||
SystemCallErrorNumber = "EPERM";
|
|
||||||
SystemCallArchitectures = "native";
|
|
||||||
LockPersonality = "yes";
|
|
||||||
IPAddressDeny = "any";
|
|
||||||
WatchdogSec = "3min";
|
|
||||||
};
|
};
|
||||||
};
|
services.logrotate.enable = false;
|
||||||
|
services.udisks2.enable = false;
|
||||||
|
system.tools.nixos-generate-config.enable = false;
|
||||||
|
system.activationScripts.specialfs = lib.mkForce "";
|
||||||
|
systemd.coredump.enable = false;
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
powerManagement.enable = false;
|
||||||
|
boot.kexec.enable = false;
|
||||||
|
console.enable = false;
|
||||||
|
|
||||||
# Configure user accounts
|
# Configure activation / systemd
|
||||||
# The immutable overlay wants userborn or sysusers.. we just want baked-in files w/o running a service.
|
boot.initrd.systemd.enable = true; # for etc.overlay, but we don't have initrd
|
||||||
# So we can just run userborn at system closure build time!
|
system.etc.overlay.enable = true; # erofs
|
||||||
systemd.sysusers.enable = false;
|
system.etc.overlay.mutable = false;
|
||||||
services.userborn.enable = true;
|
system.switch.enable = false;
|
||||||
systemd.services.userborn.enable = false;
|
services.udev.enable = lib.mkDefault true;
|
||||||
environment.etc."passwd" = lib.mkForce { source = "${userbornResults}/passwd"; mode = "0444"; };
|
services.udev.packages = lib.mkDefault [ ];
|
||||||
environment.etc."group" = lib.mkForce { source = "${userbornResults}/group"; mode = "0444"; };
|
services.resolved.enable = false;
|
||||||
environment.etc."shadow" = lib.mkForce { source = "${userbornResults}/shadow"; mode = "0440"; };
|
environment.etc."resolv.conf".source = "/run/resolv.conf";
|
||||||
users.mutableUsers = false;
|
environment.etc."machine-id".source = "/run/machine-id";
|
||||||
users.users.appvm = {
|
environment.etc."systemd/system".source = lib.mkForce (
|
||||||
uid = 1337;
|
utils.systemdUtils.lib.generateUnits {
|
||||||
group = "appvm";
|
type = "system";
|
||||||
isNormalUser = false;
|
units = config.systemd.units;
|
||||||
isSystemUser = true;
|
upstreamUnits = [
|
||||||
home = "/home/appvm";
|
"sysinit.target"
|
||||||
description = "microVM User";
|
"local-fs.target"
|
||||||
extraGroups = [ "wheel" "video" "input" "systemd-journal" ];
|
"nss-user-lookup.target"
|
||||||
};
|
"umount.target"
|
||||||
users.groups.appvm.gid = 1337;
|
"sockets.target"
|
||||||
users.allowNoPasswordLogin = true;
|
"shutdown.target"
|
||||||
|
"reboot.target"
|
||||||
|
"exit.target"
|
||||||
|
"final.target"
|
||||||
|
"systemd-exit.service"
|
||||||
|
"systemd-journald.socket"
|
||||||
|
"systemd-journald-audit.socket"
|
||||||
|
"systemd-journald-dev-log.socket"
|
||||||
|
"systemd-journald.service"
|
||||||
|
"systemd-udevd-kernel.socket"
|
||||||
|
"systemd-udevd-control.socket"
|
||||||
|
"user.slice"
|
||||||
|
];
|
||||||
|
upstreamWants = [ "multi-user.target.wants" ];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
# Configure services
|
# systemd.package = pkgs.systemdMinimal; # no analyze
|
||||||
|
systemd.defaultUnit = "microvm.target";
|
||||||
systemd.settings.Manager.DefaultEnvironment = "XDG_RUNTIME_DIR=${runtimeDir}";
|
systemd.targets.microvm = {
|
||||||
|
description = "Minimal microVM system";
|
||||||
systemd.services.muvm-remote = {
|
wants = [
|
||||||
enable = true;
|
"systemd-journald.socket"
|
||||||
description = "microVM Application runner";
|
"systemd-udevd.service"
|
||||||
onFailure = ["exit.target"];
|
"dbus.socket"
|
||||||
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";
|
unitConfig.AllowIsolate = "yes";
|
||||||
Group = "appvm";
|
};
|
||||||
ExecStartPre = "+/run/current-system/sw/bin/chown appvm:appvm ${runtimeDir}";
|
systemd.services.generate-shutdown-ramfs.enable = lib.mkForce false;
|
||||||
ExecStart = "/opt/bin/muvm-remote";
|
systemd.services.systemd-remount-fs.enable = lib.mkForce false;
|
||||||
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')))"'';
|
systemd.services.systemd-pstore.enable = lib.mkForce false;
|
||||||
} // useTTY;
|
systemd.services.lastlog2-import.enable = lib.mkForce false;
|
||||||
};
|
systemd.services.suid-sgid-wrappers.enable = lib.mkForce false;
|
||||||
|
systemd.services.systemd-udevd = {
|
||||||
|
# Redefine to remove the Before deps and get out of the critical chain
|
||||||
|
enable = true;
|
||||||
|
description = "Rule-based Manager for Device Events and Files";
|
||||||
|
unitConfig.DefaultDependencies = "no";
|
||||||
|
serviceConfig = {
|
||||||
|
CapabilityBoundingSet = "~CAP_SYS_TIME CAP_WAKE_ALARM";
|
||||||
|
Delegate = "";
|
||||||
|
DelegateSubgroup = "udev";
|
||||||
|
Type = "notify-reload";
|
||||||
|
OOMScoreAdjust = "-1000";
|
||||||
|
Sockets = "systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket";
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = "0";
|
||||||
|
ExecStart = "${pkgs.systemd}/lib/systemd/systemd-udevd";
|
||||||
|
FileDescriptorStoreMax = "512";
|
||||||
|
FileDescriptorStorePreserve = "yes";
|
||||||
|
KillMode = "mixed";
|
||||||
|
TasksMax = "infinity";
|
||||||
|
PrivateMounts = "yes";
|
||||||
|
ProtectHostname = "yes";
|
||||||
|
MemoryDenyWriteExecute = "yes";
|
||||||
|
RestrictAddressFamilies = "AF_UNIX AF_NETLINK AF_INET AF_INET6";
|
||||||
|
RestrictRealtime = "yes";
|
||||||
|
RestrictSUIDSGID = "yes";
|
||||||
|
SystemCallFilter = [
|
||||||
|
"@system-service @module @raw-io bpf"
|
||||||
|
"~@clock"
|
||||||
|
];
|
||||||
|
SystemCallErrorNumber = "EPERM";
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
LockPersonality = "yes";
|
||||||
|
IPAddressDeny = "any";
|
||||||
|
WatchdogSec = "3min";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.muvm-configure-network = {
|
# Configure user accounts
|
||||||
enable = true;
|
# The immutable overlay wants userborn or sysusers.. we just want baked-in files w/o running a service.
|
||||||
description = "microVM Network configuration";
|
# So we can just run userborn at system closure build time!
|
||||||
wantedBy = ["microvm.target"];
|
systemd.sysusers.enable = false;
|
||||||
serviceConfig.Type = "oneshot";
|
services.userborn.enable = true;
|
||||||
serviceConfig.ExecStart = "/opt/bin/muvm-configure-network";
|
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";
|
||||||
|
};
|
||||||
|
users.mutableUsers = false;
|
||||||
|
users.users.appvm = {
|
||||||
|
uid = 1337;
|
||||||
|
group = "appvm";
|
||||||
|
isNormalUser = false;
|
||||||
|
isSystemUser = true;
|
||||||
|
home = "/home/appvm";
|
||||||
|
description = "microVM User";
|
||||||
|
extraGroups = [
|
||||||
|
"wheel"
|
||||||
|
"video"
|
||||||
|
"input"
|
||||||
|
"systemd-journal"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
users.groups.appvm.gid = 1337;
|
||||||
|
users.allowNoPasswordLogin = true;
|
||||||
|
|
||||||
systemd.sockets.muvm-pwbridge = {
|
# Configure services
|
||||||
enable = true;
|
|
||||||
description = "PipeWire cross-domain proxy socket";
|
systemd.settings.Manager.DefaultEnvironment = "XDG_RUNTIME_DIR=${runtimeDir}";
|
||||||
wantedBy = ["microvm.target"];
|
|
||||||
partOf = ["muvm-pwbridge.service"];
|
systemd.services.muvm-remote = {
|
||||||
listenStreams = [ "${runtimeDir}/pipewire-0" ];
|
enable = true;
|
||||||
socketConfig = {
|
description = "microVM Application runner";
|
||||||
SocketUser = "appvm";
|
onFailure = [ "exit.target" ];
|
||||||
SocketGroup = "appvm";
|
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";
|
||||||
|
wantedBy = [ "microvm.target" ];
|
||||||
|
partOf = [ "session-bus.service" ];
|
||||||
|
listenStreams = [ "${runtimeDir}/dbus.sock" ];
|
||||||
|
socketConfig = {
|
||||||
|
SocketUser = "appvm";
|
||||||
|
SocketGroup = "appvm";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
systemd.services.session-bus = {
|
||||||
|
enable = true;
|
||||||
|
description = "D-Bus session bus";
|
||||||
|
requires = [ "session-bus.socket" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ImportCredential = "sidebus.port"; # inherited by the activated agent..
|
||||||
|
ExecStart = "${pkgs.dbus}/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --syslog-only"; # no systemd activation, we don't run a *session* systemd
|
||||||
|
User = "appvm";
|
||||||
|
Group = "appvm";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.dbus.packages = [
|
||||||
|
(pkgs.writeTextDir "/share/dbus-1/services/org.freedesktop.portal.Desktop.service" ''
|
||||||
|
[D-BUS Service]
|
||||||
|
Name=org.freedesktop.portal.Desktop
|
||||||
|
Exec=${sidebus.packages.${system}.sidebus-agent}/bin/sidebus-agent
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
hardware.graphics.enable = true;
|
||||||
|
hardware.graphics.package = self.packages.${system}.mesa;
|
||||||
|
|
||||||
|
system.build.munix = pkgs.symlinkJoin {
|
||||||
|
name = "munix";
|
||||||
|
paths = [ self.packages.${system}.munix ];
|
||||||
|
buildInputs = [ pkgs.makeWrapper ];
|
||||||
|
postBuild = ''
|
||||||
|
wrapProgram $out/bin/munix \
|
||||||
|
--add-flags ${config.system.build.toplevel} \
|
||||||
|
--set MICROVM_DEFAULT_COMMAND ${lib.escapeShellArg config.virtualisation.munix.defaultCommand}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
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";
|
|
||||||
wantedBy = ["microvm.target"];
|
|
||||||
partOf = ["session-bus.service"];
|
|
||||||
listenStreams = [ "${runtimeDir}/dbus.sock" ];
|
|
||||||
socketConfig = {
|
|
||||||
SocketUser = "appvm";
|
|
||||||
SocketGroup = "appvm";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
systemd.services.session-bus = {
|
|
||||||
enable = true;
|
|
||||||
description = "D-Bus session bus";
|
|
||||||
requires = ["session-bus.socket"];
|
|
||||||
serviceConfig = {
|
|
||||||
ImportCredential = "sidebus.port"; # inherited by the activated agent..
|
|
||||||
ExecStart = "${pkgs.dbus}/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --syslog-only"; # no systemd activation, we don't run a *session* systemd
|
|
||||||
User = "appvm";
|
|
||||||
Group = "appvm";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
services.dbus.packages = [
|
|
||||||
(pkgs.writeTextDir "/share/dbus-1/services/org.freedesktop.portal.Desktop.service" ''
|
|
||||||
[D-BUS Service]
|
|
||||||
Name=org.freedesktop.portal.Desktop
|
|
||||||
Exec=${sidebus.packages.${system}.sidebus-agent}/bin/sidebus-agent
|
|
||||||
'')
|
|
||||||
];
|
|
||||||
|
|
||||||
hardware.graphics.enable = true;
|
|
||||||
hardware.graphics.package = self.packages.${system}.mesa;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,16 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
# First, define system configuration in a module:
|
|
||||||
nixosModules.musictest =
|
nixosModules.musictest =
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
system.stateVersion = "26.05";
|
system.stateVersion = "26.05";
|
||||||
|
virtualisation.munix.defaultCommand = "euphonica";
|
||||||
|
|
||||||
programs.dconf.enable = true;
|
programs.dconf.enable = true;
|
||||||
fonts.packages = with pkgs; [ adwaita-fonts ];
|
fonts.packages = with pkgs; [ adwaita-fonts ];
|
||||||
environment.systemPackages = with pkgs; [ euphonica ];
|
environment.systemPackages = with pkgs; [ euphonica ];
|
||||||
|
|
||||||
# Local background service as a demo that doesn't require network creds :)
|
# Local background service as a demo that doesn't require network creds :)
|
||||||
services.mpd = {
|
services.mpd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -48,7 +50,6 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# And then define system closures per arch using the module above:
|
|
||||||
nixosConfigurations.musictest-aarch64 = nixpkgs.lib.nixosSystem {
|
nixosConfigurations.musictest-aarch64 = nixpkgs.lib.nixosSystem {
|
||||||
system = "aarch64-linux";
|
system = "aarch64-linux";
|
||||||
modules = [
|
modules = [
|
||||||
|
|
@ -66,31 +67,11 @@
|
||||||
|
|
||||||
apps.aarch64-linux.default = {
|
apps.aarch64-linux.default = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${
|
program = "${self.nixosConfigurations.musictest-aarch64.config.system.build.munix}/bin/munix";
|
||||||
nixpkgs.legacyPackages.aarch64-linux.symlinkJoin {
|
|
||||||
name = "munix";
|
|
||||||
paths = [ munix.packages.aarch64-linux.munix ];
|
|
||||||
buildInputs = [ nixpkgs.legacyPackages.aarch64-linux.makeWrapper ];
|
|
||||||
postBuild = ''
|
|
||||||
wrapProgram $out/bin/munix --add-flags ${self.nixosConfigurations.musictest-aarch64.config.system.build.toplevel} --set MICROVM_DEFAULT_COMMAND euphonica
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
}/bin/munix";
|
|
||||||
meta.description = "Run Music Demo App";
|
|
||||||
};
|
};
|
||||||
apps.x86_64-linux.default = {
|
apps.x86_64-linux.default = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${
|
program = "${self.nixosConfigurations.musictest-x86_64.config.system.build.munix}/bin/munix";
|
||||||
nixpkgs.legacyPackages.x86_64-linux.symlinkJoin {
|
|
||||||
name = "munix";
|
|
||||||
paths = [ munix.packages.x86_64-linux.munix ];
|
|
||||||
buildInputs = [ nixpkgs.legacyPackages.x86_64-linux.makeWrapper ];
|
|
||||||
postBuild = ''
|
|
||||||
wrapProgram $out/bin/munix --add-flags ${self.nixosConfigurations.musictest-x86_64.config.system.build.toplevel} --set MICROVM_DEFAULT_COMMAND euphonica
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
}/bin/munix";
|
|
||||||
meta.description = "Run Music Demo App";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue