uvms/profiles/baseImage.nix

456 lines
13 KiB
Nix
Raw Normal View History

{
lib,
config,
modulesPath,
pkgs,
uvmsPkgs,
...
}:
let
inherit (lib) mkOption types concatStringsSep;
jsonType = (pkgs.formats.json { }).type;
inherit (config.system.build) initialRamdisk;
inherit (config.system.boot.loader) initrdFile;
inherit (config.boot.kernelPackages) kernel;
kernelTarget = pkgs.stdenv.hostPlatform.linux-kernel.target;
waylandSock = "/run/user/1000/wayland-1";
env = {
2026-03-11 17:38:49 +02:00
DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/1000/bus";
XDG_RUNTIME_DIR = "/run/user/1000";
WAYLAND_DISPLAY = "wayland-1";
# MESA_LOADER_DRIVER_OVERRIDE = "zink";
ELECTRON_OZONE_PLATFORM_HINT = "wayland";
MOZ_ENABLE_WAYLAND = "1";
QT_QPA_PLATFORM = "wayland"; # Qt Applications
GDK_BACKEND = "wayland"; # GTK Applications
XDG_SESSION_TYPE = "wayland"; # Electron Applications
SDL_VIDEODRIVER = "wayland";
CLUTTER_BACKEND = "wayland";
NIXOS_OZONE_WL = "1";
};
in
{
imports = [
(modulesPath + "/profiles/minimal.nix")
./debug-closure.nix
./minimal.nix
./on-failure.nix
];
config = {
_module.args.uvmsPkgs = lib.mkDefault (pkgs.callPackage ../pkgs { });
# some.failure-handler.enable = true;
hardware.graphics.enable = true;
2026-03-10 02:01:54 +02:00
# boot.kernelPackages = pkgs.linuxPackagesFor uvmsPkgs.linux-uvm;
# boot.isContainer = true;
2026-03-22 16:19:11 +02:00
boot.kernel.sysctl = {
"vm.overcommit_memory" = 1; # "always"
# "vm.overcommit_memory" = 2; # "never"
"vm.panic_on_oom" = 1;
};
boot.initrd.kernelModules = [
"drm"
"virtio_blk"
"virtiofs"
"virtio_gpu"
"virtio_mmio"
"virtio_pci"
"overlay"
];
boot.kernelModules = [
"drm"
"erofs"
"overlay"
"virtio_blk"
"virtiofs"
"virtio_gpu"
"virtio_mmio"
"virtio_pci"
];
boot.initrd.systemd.initrdBin = [
pkgs.fuse
pkgs.fuse3
];
fileSystems = {
"/" = lib.mkDefault {
device = "rootfs"; # how does this work? does this assign a label to the tmpfs?
fsType = "tmpfs";
options = [ "size=20%,mode=0755" ];
neededForBoot = true;
};
"/nix/store" = {
fsType = "overlay";
overlay.lowerdir = [
"/nix/.ro-stores/system"
"/nix/.ro-stores/apps"
];
neededForBoot = true;
};
"/nix/.ro-stores/system" = {
device = "system";
fsType = "virtiofs";
options = [
"defaults"
"ro"
"x-systemd.requires=systemd-modules-load.service"
];
neededForBoot = true;
};
"/nix/.ro-stores/apps" = {
device = "apps";
fsType = "virtiofs";
options = [
"defaults"
"ro"
"x-systemd.requires=systemd-modules-load.service"
];
neededForBoot = true;
};
};
2026-03-11 17:38:49 +02:00
programs.dconf.enable = true;
systemd.mounts = [
{
type = "virtiofs";
where = "/home/user";
what = "home";
after = [ "systemd-modules-load.service" ];
wantedBy = [ "local-fs.target" ];
before = [ "local-fs.target" ];
requires = [ "systemd-modules-load.service" ];
options = lib.concatStringsSep "," [
"defaults"
"rw"
"X-mount.owner=1000"
"X-mount.group=100"
];
unitConfig = {
ConditionKernelCommandLine = "uvms.persist-home=1";
};
}
{
type = "virtiofs";
where = "/home/user/send";
what = "send";
wants = [
"home-user.mount"
"-.mount"
];
after = [
"systemd-modules-load.service"
"home-user.mount"
"-.mount"
];
wantedBy = [ "local-fs.target" ];
before = [ "local-fs.target" ];
options = lib.concatStringsSep "," [
"defaults"
"rw"
"X-mount.owner=1000"
"X-mount.group=100"
];
unitConfig = {
DefaultDependencies = false;
};
}
];
# systemd.services."mount-home-user-send" = {
# wants = [ "home-user.mount" ];
# after = [
# "systemd-modules-load.service"
# "home-user.mount"
# "-.mount"
# ];
# wantedBy = [ "local-fs.target" ];
# before = [ "local-fs.target" ];
# unitConfig = {
# DefaultDependencies = false;
# };
# environment.PATH = lib.mkForce (
# lib.makeBinPath [
# pkgs.fuse
# pkgs.fuse3
# pkgs.coreutils
# ]
# );
# serviceConfig = {
# Type = "oneshot";
# RemainsAfterExit = true;
# ExecStart = [
# "/run/current-system/sw/bin/mkdir -p /home/user/send"
# "/run/current-system/sw/bin/chown user /home/user/send"
# "/run/current-system/sw/sbin/mount -t virtiofs -o defaults,rw send /home/user/send"
# ];
# StandardOutput = "journal+console";
# StandardError = "journal+console";
# };
# };
systemd.network.enable = true;
networking.useNetworkd = true;
networking.nftables.enable = true;
networking.useDHCP = true;
networking.nameservers = [ "1.1.1.1" ];
services.resolved.enable = lib.mkForce true;
system.activationScripts.specialfs = lib.mkForce "";
# networking.firewall.enable = false;
console.enable = false;
services.udev.packages = lib.mkDefault [ ];
systemd.services."systemd-oomd".enable = false;
users.mutableUsers = false;
users.users.root.password = "hacktheplanet!";
users.groups.users = { };
users.users.user = {
uid = 1000;
isNormalUser = true;
password = "hacktheplanet!";
extraGroups = [
"video"
"render"
"users"
"wheel"
];
};
environment.profileRelativeSessionVariables.PATH = lib.mkForce [ "/bin\${PATH:+:}$PATH" ];
2026-03-15 02:15:58 +02:00
environment.profileRelativeSessionVariables.XDG_DATA_DIRS = lib.mkForce [ "/run/current-system/sw/share/\${XDG_DATA_DIRS:+:}$XDG_DATA_DIRS" ];
2026-03-11 17:38:49 +02:00
environment.sessionVariables = env;
environment.variables = env;
systemd.globalEnvironment = env;
systemd.tmpfiles.settings."10-xdg" = {
${env.XDG_RUNTIME_DIR}.d = {
user = "user";
group = "users";
mode = "0755";
};
};
systemd.sockets."wayland-proxy" = {
listenStreams = [
waylandSock
];
socketConfig = {
SocketUser = "user";
SocketGroup = "users";
FileDescriptorName = "wayland";
};
wantedBy = [ "sockets.target" ];
partOf = [ "wayland-proxy.service" ];
};
systemd.services."wayland-proxy" = {
wantedBy = [ "default.target" ];
serviceConfig = {
User = "user";
Group = "users";
ExecStart = "${lib.getExe pkgs.wayland-proxy-virtwl} --virtio-gpu";
# ExecStart = "${lib.getExe uvmsPkgs.wl-cross-domain-proxy} --listen-fd --filter-global wp_presentation";
ExecStartPre = [
"+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128"
];
StandardOutput = "journal+console";
StandardError = "journal+console";
Restart = "on-failure";
RestartSec = 5;
};
};
systemd.sockets."uvms-guest" = {
2026-03-10 02:01:54 +02:00
requiredBy = [ "multi-user.target" ];
before = [ "multi-user.target" ];
listenStreams = [
"vsock::24601"
];
partOf = [ "uvms-guest.service" ];
};
systemd.services."uvms-guest" = {
2026-03-10 02:01:54 +02:00
before = [ "multi-user.target" ];
onFailure = [ "shutdown.service" ];
serviceConfig = {
User = "user";
Group = "users";
2026-03-10 02:01:54 +02:00
ExecStart = "${lib.getExe' uvmsPkgs.uvmslib "uvms-guest"}";
ExecStop = [
"/run/current-system/sw/bin/echo GUEST DOWN"
"/run/current-system/sw/bin/systemctl poweroff"
];
StandardOutput = "journal+console";
StandardError = "journal+console";
Restart = "no";
};
};
systemd.services."shutdown" = {
serviceConfig = {
ExecStart = [ "/run/current-system/sw/bin/systemctl poweroff" ];
StandardOutput = "journal+console";
StandardError = "journal+console";
};
};
fonts.enableDefaultPackages = true;
boot.kernelParams = [
"earlyprintk=ttyS0"
"console=ttyS0"
"reboot=t"
"panic=-1"
# "rootfstype=virtiofs"
# "root=rootstore"
];
};
options = {
system.build.ch = mkOption {
type = types.package;
default = (pkgs.formats.json { }).generate "vm.json" config.uvms.ch.settings;
};
uvms.ch.settings = mkOption {
default = { };
type = types.submodule (
2026-03-11 17:38:49 +02:00
let
osConfig = config;
in
{ config, ... }:
{
freeformType = jsonType;
options = {
payload = {
cmdline = mkOption {
type = types.str;
default = concatStringsSep " " (
osConfig.boot.kernelParams
++ [
# "init=${lib.removePrefix "/nix/store" "${osConfig.system.build.toplevel}"}/init"
"init=${osConfig.system.build.toplevel}/init"
]
);
defaultText = ''concatStringsSep " " ${osConfig.boot.kernelParams}'';
};
kernel = mkOption {
type = types.str;
default = "${kernel}/${kernelTarget}";
};
initramfs = mkOption {
type = types.nullOr types.str;
default = "${initialRamdisk}/${initrdFile}";
};
};
vsock = {
cid = mkOption {
type = types.int;
default = 4;
};
socket = mkOption {
type = types.str;
default = "vsock.sock";
};
};
"api-socket" = mkOption {
type = types.str;
default = "vmm.sock";
};
"serial".mode = mkOption {
type = types.str;
default = "File";
};
"serial".file = mkOption {
type = types.nullOr types.str;
default = "serial";
};
"console".mode = mkOption {
type = types.str;
default = "Pty";
};
"console".file = mkOption {
type = types.nullOr types.str;
default = null;
};
# "watchdog" = true;
# "seccomp" = true;
disks = mkOption {
default = [ ];
type = types.listOf (
types.submodule {
freeformType = jsonType;
options = {
path = mkOption {
type = types.oneOf [
types.path
types.str
];
};
readonly = mkOption {
type = types.bool;
default = true;
};
id = mkOption { type = types.str; };
};
}
);
};
memory = mkOption {
default = { };
type = types.submodule {
freeformType = jsonType;
options = {
size = mkOption {
type = types.int;
2026-03-10 02:01:54 +02:00
default = 4 * 1024 * 1048576;
};
shared = mkOption {
type = types.bool;
default = true;
};
mergeable = mkOption {
type = types.bool;
default = true;
};
hotplug_method = mkOption {
default = "VirtioMem";
type = types.enum [
"Acpi"
"VirtioMem"
];
};
hotplugged_size = mkOption {
type = types.int;
default = 512 * 1048576;
};
hotplug_size = mkOption {
type = types.int;
default = config.memory.size;
};
# hugepages = mkOption {
# type = types.bool;
# default = true;
# };
};
};
};
cpus = mkOption {
default = { };
type = types.submodule {
freeformType = jsonType;
options = {
boot_vcpus = mkOption {
type = types.int;
default = 4;
};
max_vcpus = mkOption {
type = types.int;
default = 4;
};
};
};
};
};
}
);
};
};
}