feat: add per-VM tray.enable option (default false)
Tray proxy was unconditionally enabled for all crosvm VMs. Add tray.enable so it must be opted into per VM. When disabled, neither the host-side tray service nor the guest-side tray daemon are created. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f18d362efe
commit
2aec448e71
4 changed files with 65 additions and 50 deletions
|
|
@ -171,6 +171,7 @@ There are a lot of configuration options but you don't really need to touch most
|
|||
| `color` | string | `"darkred"` | Window decoration color (named color or hex, e.g., `"#2ecc71"`) |
|
||||
| `network.nameservers` | list of strings | `[]` | DNS nameservers for this VM |
|
||||
| `network.interfaces` | attrset of interface configs | `{}` | Network interfaces (keys are guest-visible names) |
|
||||
| `tray.enable` | bool | `false` | Enable tray proxy for this VM (proxies guest SNI tray items to host system tray) |
|
||||
| `autoShutdown.enable` | bool | `false` | Auto-shutdown when idle (after `autoShutdown.after` seconds) |
|
||||
| `autoShutdown.after` | int | `60` | Seconds to wait before shutdown |
|
||||
| `autoStart` | bool | `false` | Start VM automatically (GPU VMs: on session start; non-GPU VMs: at boot) |
|
||||
|
|
@ -575,7 +576,7 @@ The host provides:
|
|||
|
||||
### Tray Integration
|
||||
|
||||
VM system tray applets (StatusNotifierItems like nm-applet, bluetooth, etc.) automatically appear in the host KDE system tray. No configuration needed — tray proxying is always enabled.
|
||||
VM system tray applets (StatusNotifierItems like nm-applet, bluetooth, etc.) can appear in the host KDE system tray. Enable per VM with `tray.enable = true`.
|
||||
|
||||
- Tray items are prefixed with the VM name (e.g., `[banking] NetworkManager`)
|
||||
- User interactions (clicks, scrolls, context menus) are forwarded back to the guest app
|
||||
|
|
|
|||
|
|
@ -251,6 +251,20 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
tray = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Enable host-side tray proxy for this VM. Proxies guest SNI tray items to the host system tray.";
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = "Tray proxy configuration for this VM.";
|
||||
};
|
||||
|
||||
autoShutdown = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
|
|
|
|||
|
|
@ -498,7 +498,7 @@ let
|
|||
pkgs.callPackage ../rootfs-nixos {
|
||||
inherit (cfg._internal) wayland-proxy-virtwl sommelier;
|
||||
inherit soundConfig;
|
||||
vmsilo-tray = cfg._internal.vmsilo-tray;
|
||||
vmsilo-tray = if vm.tray.enable then cfg._internal.vmsilo-tray else null;
|
||||
trayLogLevel = cfg.vmsilo-tray.logLevel;
|
||||
waylandProxy = vm.waylandProxy;
|
||||
guestPrograms = vm.guestPrograms;
|
||||
|
|
|
|||
|
|
@ -275,53 +275,53 @@ in
|
|||
}
|
||||
) (lib.attrValues cfg.nixosVms)
|
||||
++
|
||||
# VM services (run crosvm as root)
|
||||
map (
|
||||
vm:
|
||||
lib.nameValuePair "vmsilo-${vm.name}-vm" {
|
||||
description = "vmsilo VM: ${vm.name}";
|
||||
wantedBy = lib.optionals (vm.autoStart && vm.gpu == false) [ "multi-user.target" ];
|
||||
wants =
|
||||
map (depName: "vmsilo-${depName}-vm.service") vm.dependsOn
|
||||
++ lib.optional (
|
||||
vm.network.netvm != null && vm.network.netvm != "host"
|
||||
) "vmsilo-${vm.network.netvm}-vm.service"
|
||||
++ map (brName: "${brName}-netdev.service") (vmBridges vm);
|
||||
after = [ "network.target" ] ++ map (brName: "${brName}-netdev.service") (vmBridges vm);
|
||||
serviceConfig =
|
||||
let
|
||||
ephemeralPath = "/var/lib/vmsilo/${vm.name}-ephemeral.raw";
|
||||
createEphemeral = pkgs.writeShellScript "create-ephemeral-${vm.name}" ''
|
||||
truncate -s ${vm.rootOverlay.size} ${ephemeralPath}
|
||||
'';
|
||||
deleteEphemeral = pkgs.writeShellScript "delete-ephemeral-${vm.name}" ''
|
||||
rm -f ${ephemeralPath}
|
||||
'';
|
||||
startPreScripts = lib.optionals (vm.rootOverlay.type == "raw") [ "${createEphemeral}" ];
|
||||
cleanupSocket = pkgs.writeShellScript "cleanup-socket-${vm.name}" ''
|
||||
rm -f /run/vmsilo/${vm.name}/crosvm-control.socket
|
||||
rm -f /run/vmsilo/${vm.name}/cloud-hypervisor-control.socket
|
||||
'';
|
||||
usbCleanup = pkgs.writeShellScript "usb-cleanup-${vm.name}" ''
|
||||
source ${cfg._internal.usbHelperLib}
|
||||
usb_cleanup_vm "${vm.name}"
|
||||
'';
|
||||
stopPostScripts = [
|
||||
"${cleanupSocket}"
|
||||
]
|
||||
++ lib.optional (vm.hypervisor == "crosvm") "${usbCleanup}"
|
||||
++ lib.optionals (vm.rootOverlay.type == "raw") [ "${deleteEphemeral}" ];
|
||||
in
|
||||
{
|
||||
Type = "simple";
|
||||
ExecStart = "${cfg._internal.vmScripts.${vm.name}}";
|
||||
ExecStopPost = stopPostScripts;
|
||||
}
|
||||
// lib.optionalAttrs (startPreScripts != [ ]) {
|
||||
ExecStartPre = startPreScripts;
|
||||
};
|
||||
}
|
||||
) (lib.attrValues cfg.nixosVms)
|
||||
# VM services (run crosvm as root)
|
||||
map (
|
||||
vm:
|
||||
lib.nameValuePair "vmsilo-${vm.name}-vm" {
|
||||
description = "vmsilo VM: ${vm.name}";
|
||||
wantedBy = lib.optionals (vm.autoStart && vm.gpu == false) [ "multi-user.target" ];
|
||||
wants =
|
||||
map (depName: "vmsilo-${depName}-vm.service") vm.dependsOn
|
||||
++ lib.optional (
|
||||
vm.network.netvm != null && vm.network.netvm != "host"
|
||||
) "vmsilo-${vm.network.netvm}-vm.service"
|
||||
++ map (brName: "${brName}-netdev.service") (vmBridges vm);
|
||||
after = [ "network.target" ] ++ map (brName: "${brName}-netdev.service") (vmBridges vm);
|
||||
serviceConfig =
|
||||
let
|
||||
ephemeralPath = "/var/lib/vmsilo/${vm.name}-ephemeral.raw";
|
||||
createEphemeral = pkgs.writeShellScript "create-ephemeral-${vm.name}" ''
|
||||
truncate -s ${vm.rootOverlay.size} ${ephemeralPath}
|
||||
'';
|
||||
deleteEphemeral = pkgs.writeShellScript "delete-ephemeral-${vm.name}" ''
|
||||
rm -f ${ephemeralPath}
|
||||
'';
|
||||
startPreScripts = lib.optionals (vm.rootOverlay.type == "raw") [ "${createEphemeral}" ];
|
||||
cleanupSocket = pkgs.writeShellScript "cleanup-socket-${vm.name}" ''
|
||||
rm -f /run/vmsilo/${vm.name}/crosvm-control.socket
|
||||
rm -f /run/vmsilo/${vm.name}/cloud-hypervisor-control.socket
|
||||
'';
|
||||
usbCleanup = pkgs.writeShellScript "usb-cleanup-${vm.name}" ''
|
||||
source ${cfg._internal.usbHelperLib}
|
||||
usb_cleanup_vm "${vm.name}"
|
||||
'';
|
||||
stopPostScripts = [
|
||||
"${cleanupSocket}"
|
||||
]
|
||||
++ lib.optional (vm.hypervisor == "crosvm") "${usbCleanup}"
|
||||
++ lib.optionals (vm.rootOverlay.type == "raw") [ "${deleteEphemeral}" ];
|
||||
in
|
||||
{
|
||||
Type = "simple";
|
||||
ExecStart = "${cfg._internal.vmScripts.${vm.name}}";
|
||||
ExecStopPost = stopPostScripts;
|
||||
}
|
||||
// lib.optionalAttrs (startPreScripts != [ ]) {
|
||||
ExecStartPre = startPreScripts;
|
||||
};
|
||||
}
|
||||
) (lib.attrValues cfg.nixosVms)
|
||||
++
|
||||
# Proxy template services (per-connection)
|
||||
map (
|
||||
|
|
@ -478,7 +478,7 @@ in
|
|||
# Tray proxy services (crosvm VMs only — kernel vsock required)
|
||||
lib.concatMap (
|
||||
vm:
|
||||
lib.optional (vm.hypervisor == "crosvm") (
|
||||
lib.optional (vm.tray.enable && vm.hypervisor == "crosvm") (
|
||||
lib.nameValuePair "vmsilo-${vm.name}-tray" {
|
||||
description = "Tray proxy for VM ${vm.name}";
|
||||
wantedBy = [ "vmsilo-${vm.name}-vm.service" ];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue