profiles/vmapp-demo: init MVE
...moving bits and pieces from .dotfiles
This commit is contained in:
parent
b2b9628ed6
commit
a25e51e7da
4 changed files with 336 additions and 5 deletions
|
@ -13,6 +13,9 @@
|
||||||
|
|
||||||
system.stateVersion = "25.11";
|
system.stateVersion = "25.11";
|
||||||
|
|
||||||
|
vmapps.enable = true;
|
||||||
|
_module.args.inputs = import ../npins;
|
||||||
|
|
||||||
# following microvm.nix:
|
# following microvm.nix:
|
||||||
boot.loader.grub.enable = false;
|
boot.loader.grub.enable = false;
|
||||||
boot.initrd.systemd.enable = true;
|
boot.initrd.systemd.enable = true;
|
||||||
|
@ -22,9 +25,8 @@
|
||||||
options = [ "size=20%,mode=0755" ];
|
options = [ "size=20%,mode=0755" ];
|
||||||
neededForBoot = true;
|
neededForBoot = true;
|
||||||
};
|
};
|
||||||
boot.initrd.systemd.emergencyAccess = true;
|
boot.initrd.systemd.settings.Manager.DefaultTimeoutStartSec = 30;
|
||||||
boot.initrd.systemd.settings.Manager.DefaultTimeoutStartSec = 15;
|
systemd.settings.Manager.DefaultTimeoutStopSec= 10;
|
||||||
systemd.settings.Manager.DefaultTimeoutStartSec = 15;
|
|
||||||
networking.useNetworkd = true;
|
networking.useNetworkd = true;
|
||||||
networking.nftables.enable = true;
|
networking.nftables.enable = true;
|
||||||
|
|
||||||
|
@ -32,7 +34,12 @@
|
||||||
|
|
||||||
users.mutableUsers = false;
|
users.mutableUsers = false;
|
||||||
users.users.root.password = "hacktheplanet!";
|
users.users.root.password = "hacktheplanet!";
|
||||||
|
services.getty.autologinUser = "root";
|
||||||
|
|
||||||
|
systemd.services."suid-sgid-wrappers".serviceConfig = {
|
||||||
|
StandardOutput = "journal+console";
|
||||||
|
StandardError = "journal+console";
|
||||||
|
};
|
||||||
|
|
||||||
# TODO: cmdline, kernel, initrd, fileSystems
|
# TODO: cmdline, kernel, initrd, fileSystems
|
||||||
}
|
}
|
||||||
|
|
65
pkgs/desktopAdapters.nix
Normal file
65
pkgs/desktopAdapters.nix
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
newScope,
|
||||||
|
makeDesktopItem,
|
||||||
|
writeShellScriptBin,
|
||||||
|
}:
|
||||||
|
|
||||||
|
lib.makeScope newScope (self: {
|
||||||
|
# Scope-level configuration for adapters
|
||||||
|
useSessionUnits = true; # use --user units, instead of system units
|
||||||
|
vmUnitPrefix = "uvm@";
|
||||||
|
vmSshPrefix = if self.useSessionUnits then "uuvm/" else "uvm/";
|
||||||
|
vmUser = "user";
|
||||||
|
waylandProxyUnit = "wayland-proxy.service"; # could be sommelier
|
||||||
|
oomScoreAdjust = -200;
|
||||||
|
|
||||||
|
# Helper scripts
|
||||||
|
mkRunInVM = vmName: lib.getExe (self.mkRunInVMPkg vmName);
|
||||||
|
mkRunInVMPkg =
|
||||||
|
vmName:
|
||||||
|
writeShellScriptBin "run-in-${vmName}" ''
|
||||||
|
localArgs=(
|
||||||
|
${lib.optionalString self.useSessionUnits "--user"}
|
||||||
|
--property=Requires=${self.vmUnitPrefix}${vmName}.service
|
||||||
|
--property=After=${self.vmUnitPrefix}${vmName}.service
|
||||||
|
--property=SyslogIdentifier="$1 (${vmName})"
|
||||||
|
)
|
||||||
|
remoteArgs=(
|
||||||
|
systemd-run
|
||||||
|
--user
|
||||||
|
--property=StandardError="journal+console"
|
||||||
|
--property=StandardOutput="journal+console"
|
||||||
|
--property=OOMScoreAdjust=${toString self.oomScoreAdjust}
|
||||||
|
${lib.optionalString (self.waylandProxyUnit != null) ''
|
||||||
|
--property=Requires=${self.waylandProxyUnit}
|
||||||
|
--property=After=${self.waylandProxyUnit}
|
||||||
|
''}
|
||||||
|
)
|
||||||
|
systemd-run \
|
||||||
|
"''${localArgs[@]}" \
|
||||||
|
ssh ${self.vmUser}@${self.vmSshPrefix}${vmName} \
|
||||||
|
"''${remoteArgs[@]}" $@
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Actual .desktop item adapters
|
||||||
|
toVM =
|
||||||
|
vmName: attrs:
|
||||||
|
attrs
|
||||||
|
// {
|
||||||
|
exec = "${self.mkRunInVM vmName} ${attrs.exec}";
|
||||||
|
};
|
||||||
|
toBrowser =
|
||||||
|
attrs:
|
||||||
|
attrs
|
||||||
|
// {
|
||||||
|
categories = attrs.categories or [ ] ++ [
|
||||||
|
"WebBrowser"
|
||||||
|
"Network"
|
||||||
|
];
|
||||||
|
mimeTypes = attrs.mimeTypes or [ ] ++ [
|
||||||
|
"x-scheme-handler/http"
|
||||||
|
"x-scheme-handler/https"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
|
@ -33,10 +33,8 @@ in
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
|
||||||
boot.kernelParams = [ "zswap.enabled=1" ];
|
boot.kernelParams = [ "zswap.enabled=1" ];
|
||||||
zramSwap.enable = false;
|
zramSwap.enable = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
261
profiles/vmapp-demo.nix
Normal file
261
profiles/vmapp-demo.nix
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
{
|
||||||
|
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";
|
||||||
|
})
|
||||||
|
)
|
||||||
|
))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
]
|
||||||
|
))
|
||||||
|
];
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue