uvms/profiles/vmapp-demo.nix

262 lines
8.2 KiB
Nix
Raw Normal View History

{
options,
config,
lib,
pkgs,
modulesPath,
...
}:
let
cfg = config.vmapps;
desktopItems' = pkgs.callPackage ../pkgs/desktopAdapters.nix { };
desktopItems = desktopItems'.overrideScope (
_: pre: {
vmUser = "root";
waylandProxyUnit =
if config.microvm.graphics.enable or false then "wayland-proxy.service" else null;
}
);
nixosSystem = import (pkgs.path + "/nixos/lib/eval-config.nix");
mkStaticVM =
name: extraModules: extraHostModules:
let
evaluated = nixosSystem {
inherit (pkgs.stdenv) system;
inherit pkgs;
modules = extraModules ++ [
{
microvm.hypervisor = "cloud-hypervisor";
microvm.hotpluggedMem = 128;
microvm.hotplugMem = 512;
microvm.shares = [
{
source = "send";
mountPoint = "/home/user/uvms/${name}/send";
tag = "rw-send";
proto = "virtiofs";
}
{
source = "authorized_keys.d";
mountPoint = "/etc/ssh/authorized_keys.d";
tag = "ro-auth-keys";
proto = "virtiofs";
}
];
networking.hostName = name;
services.openssh.enable = true;
}
./uvms-guest.nix
./vsock-connect-guest.nix
(modulesPath + "/profiles/minimal.nix")
(config._module.args.inputs."microvm.nix" + "/nixos-modules/microvm")
];
specialArgs = {
inherit (config._module.args) inputs;
};
};
runner = evaluated.config.microvm.declaredRunner;
in
lib.mkMerge (
extraHostModules
++ [
(lib.mkIf (options ? "debug"."closure"."layers") {
debug.closure.extraLayers = [ runner ];
})
{
systemd.user.targets.default.wants = [ "uvm@${name}.service" ];
# TODO: Ugly dirty hack, we didn't have the time to arrange a more
# sensible workaround for CH trying to create TAPs, or to figure out
# which of the services actually need the extra permissions (probably
# microvm-run and tap-up)
security.wrappers = lib.listToAttrs (
map
(
exe:
lib.nameValuePair "${exe}-${name}" {
owner = "root";
group = "kvm";
setuid = false;
capabilities = "cap_net_admin+ep";
source = pkgs.writeShellScript "${exe}-${name}" ''
PATH=${lib.getBin pkgs.util-linux}/bin''${PATH:+:}''${PATH}
PATH=${lib.getBin runner}/bin''${PATH:+:}''${PATH}
${exe} $@
'';
}
)
[
"microvm-run"
"microvm-shutdown"
"virtiofsd-run"
"virtiofsd-shutdown"
"tap-up"
"tap-down"
]
);
}
]
);
# TODO: clean up; came out of copy-pasting stuff backnforth
preamble = ''
set -euo pipefail
INSTANCE="$1"
shift
STATE_DIR="$HOME/uvms/$INSTANCE"
mkdir -p "$STATE_DIR"
QUICKSHARE_DIR="$HOME/uvms/$INSTANCE/send"
mkdir -p "$QUICKSHARE_DIR"
cd "$STATE_DIR"
mkdir -p "$STATE_DIR"/authorized_keys.d
(
umask 0077 \
&& cp --no-preserve=all /etc/ssh/ssh_host_ed25519_key.pub "$STATE_DIR"/authorized_keys.d/root \
&& cp --no-preserve=all /etc/ssh/ssh_host_ed25519_key.pub "$STATE_DIR"/authorized_keys.d/user \
)
PATH=/run/wrappers/bin''${PATH:+:}''${PATH}
set -x
'';
in
{
options = {
vmapps.enable = lib.mkEnableOption "Enable \"VM Apps\" demo";
};
# demo is currently based on microvm.nix
config = lib.mkMerge [
(lib.mkIf (!(config._module.args ? "inputs"."microvm.nix")) { vmapps.enable = false; })
(lib.mkIf cfg.enable {
networking.useNetworkd = true;
networking.nftables.enable = true;
systemd.network.enable = true;
networking.firewall.extraInputRules = ''
iifname "vt-*" udp dport { 53, 67 } accept
'';
networking.nat.internalInterfaces = [ "vt-*" ];
users.motd = ''
vmapp-demo.nix
==============
Check `systemctl status --user uvm@browser`.
Run a command inside the VM: `run-in-browser echo foo`,
and see the outputs in syslog: `journalctl --user -u uvm@browser -e`
'';
systemd.user.services."root-ssh-keys" = {
wantedBy = [ "default.target" ];
before = [ "default.target" ];
script = ''
[[ "$USER" == "root" ]] || exit 0
[[ -f "$HOME/.ssh/config" ]] && echo ".ssh/config already exists, not writing" && exit 0
cat > "$HOME/.ssh/config" << \EOF
Host *
IdentityFile /etc/ssh/ssh_host_ed25519_key
EOF
'';
};
systemd.user.services."uvm@" = rec {
requires = [
"virtiofsd@.service"
"taps@.service"
];
after = requires;
serviceConfig.Type = "notify";
serviceConfig.LimitMEMLOCK = "infinity";
serviceConfig.LimitNOFILE = 1048576;
serviceConfig.NotifyAccess = "all";
serviceConfig.ExecStop = "${pkgs.writeShellScript "microvm-shutdown-instance" ''
${preamble}
microvm-shutdown-"$INSTANCE"
''} %i";
serviceConfig.ExecStart = "${pkgs.writeShellScript "uuvm-start-instance" ''
${preamble}
microvm-run-"$INSTANCE"
''} %i";
};
systemd.user.services."virtiofsd@" = {
requires = [ "graphical-session.target" ];
after = [ "graphical-session.target" ];
serviceConfig.Type = "notify";
serviceConfig.LimitMEMLOCK = "infinity";
serviceConfig.LimitNOFILE = 1048576;
serviceConfig.NotifyAccess = "all";
serviceConfig.ExecStop = "${pkgs.writeShellScript "virtiofsd-shutdown-instance" ''
${preamble}
virtiofsd-shutdown-"$INSTANCE"
''} %i";
serviceConfig.ExecStart = "${pkgs.writeShellScript "virtiofsd-start-instance" ''
${preamble}
virtiofsd-run-"$INSTANCE"
''} %i";
};
systemd.user.services."taps@" = {
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = true;
serviceConfig.SyslogIdentifier = "taps@";
serviceConfig.LimitMEMLOCK = "infinity";
serviceConfig.NotifyAccess = "all";
serviceConfig.ExecStop = "${pkgs.writeShellScript "taps-down-instance" ''
${preamble}
tap-down-"$INSTANCE"
''} %i";
serviceConfig.ExecStart = "${pkgs.writeShellScript "taps-start-instance" ''
${preamble}
tap-up-"$INSTANCE"
''} %i";
};
boot.initrd.systemd.settings.Manager.DefaultTimeoutStartSec = 30;
systemd.settings.Manager.DefaultTimeoutStopSec = 10;
systemd.services."user@".serviceConfig.TimeoutStopSec = 10;
services.openssh.enable = true;
environment.systemPackages = [ pkgs.xdg-utils ];
users.users.microvm.isSystemUser = true;
users.users.microvm.group = "kvm";
})
(lib.mkIf cfg.enable (
mkStaticVM "browser"
[
{
microvm.interfaces = [
{
type = "tap";
id = "vt-browse";
mac = "00:00:00:00:00:02";
}
];
environment.systemPackages = [ pkgs.tor-browser ];
}
]
[
{
environment.systemPackages = [
(desktopItems.mkRunInVMPkg "browser")
(pkgs.makeDesktopItem (
desktopItems.toBrowser (
(desktopItems.toVM "browser" {
name = "tor-browser";
exec = "tor-browser %U";
icon = "${pkgs.tor-browser}/share/icons/hicolor/128x128/apps/tor-browser.png";
desktopName = "Tor (uuvm/browser)";
startupNotify = true;
terminal = false;
type = "Application";
})
)
))
];
}
]
))
];
}