1
1
Fork 0

Compare commits

...

16 commits

Author SHA1 Message Date
cdf117daa2
mynix: work around secondary gpu reset
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:54:17 -06:00
1346b1ca63
storage: add mounts by label
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:53:38 -06:00
c3a1eb812c
vm: add gpu passthrough options
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:51:19 -06:00
67d2373cec
hyprland: update devices
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:49:48 -06:00
7e3d4ebd41
chore: fix formatting
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:49:29 -06:00
16c295d7c1
nix: use tmpfiles.settings instead of rules
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:48:23 -06:00
8bde5c66e6
chore: add todo
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:47:36 -06:00
ff1c7502a5
looking-glass: initial module
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:47:20 -06:00
bef143852a
hyprland: add virt-manager bind
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:46:07 -06:00
f5aa5e4bbf
firefox: disable tab detach
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:45:45 -06:00
e16354b0ef
firefox: force software webrender
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:45:30 -06:00
7aa3204141
samba: fix executables on windows
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:44:57 -06:00
54539758ad
kernel: update to linux 6.12
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:44:34 -06:00
a56408403c
pkgs: add mesa-demos and vulkan-tools
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:44:18 -06:00
63fc603f07
sudo: add confirmation prompt
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:44:03 -06:00
de8f54ead2
iommu.sh: initial script
Signed-off-by: Myned <dev@bjork.tech>
2024-12-06 19:43:29 -06:00
28 changed files with 430 additions and 239 deletions

View file

@ -5,19 +5,4 @@
];
custom.hostname = "myeck";
fileSystems = {
"/mnt/external" = {
device = "/dev/disk/by-label/external";
options = [
"noatime"
"nofail"
"users"
"exec"
"x-gvfs-show"
];
};
};
systemd.tmpfiles.rules = ["z /mnt/external 0755 myned users"];
}

View file

@ -1,4 +1,4 @@
{
{config, ...}: {
imports = [
./disko.nix
./hardware-configuration.nix
@ -9,6 +9,20 @@
width = 3440;
height = 1440;
refresh = 100;
settings = {
storage.mnt = ["gayme" "myve"];
vm.passthrough = {
enable = true;
driver = "amdgpu";
guest = "myndows";
id = "1002:73df";
init = true;
intel = true;
node = "pci_0000_03_00_0";
};
};
};
boot = {
@ -32,85 +46,14 @@
# `- \`_`"'-
#// services.logind.powerKey = "ignore"; # Disable power button
# Mount external drives on boot
fileSystems = {
"/mnt/gayme" = {
device = "/dev/disk/by-label/gayme";
options = [
"noatime"
"nofail"
"users"
"exec"
"x-gvfs-show"
];
};
"/mnt/gaymer" = {
device = "/dev/disk/by-label/gaymer";
options = [
"noatime"
"nofail"
"users"
"exec"
"x-gvfs-show"
home-manager.users.${config.custom.username} = {
# Prevent secondary GPU reset from crashing window manager
wayland.windowManager.hyprland.settings = {
monitor = [
"HDMI-A-1, disable"
"HDMI-A-2, disable"
"HDMI-A-3, disable"
];
};
};
# Set mount directory permissions
#?? TYPE PATH MODE USER GROUP AGE ARGUMENT
systemd.tmpfiles.rules = [
"z /mnt/gayme 0755 myned users"
"z /mnt/gaymer 0755 myned users"
];
# BUG: "manual" profile is the same as "auto" with kernel 6.10
# TODO: Remove when Linux 6.12 is released
# https://gitlab.freedesktop.org/agd5f/linux/-/commit/ec1aab7816b06c32f42935e34ce3a3040c778afb
# Work around performance issues with AMD power scaling
# https://wiki.archlinux.org/title/AMDGPU#Screen_artifacts_and_frequency_problem
# https://wiki.archlinux.org/title/AMDGPU#Power_profiles
#!! cardX must match the correct gpu
#?? lspci
#?? ls -l /dev/dri/by-path/*-card
#?? grep '*' /sys/class/drm/card*/device/pp_power_profile_mode
services.udev.extraRules = ''
SUBSYSTEM=="drm", KERNEL=="card1", DRIVERS=="amdgpu", ATTR{device/power_dpm_force_performance_level}="manual", ATTR{device/pp_power_profile_mode}="1"
'';
# https://github.com/Zygo/bees
# Deduplicate entire filesystem
#?? Optimal for ~1TB total disk space
# https://github.com/Zygo/bees/blob/master/docs/config.md#hash-table-sizing
# services.beesd.filesystems.root = {
# spec = "/";
# verbosity = "err";
# extraOptions = [ "--loadavg-target" "5" ]; # Reduce threads on ~5% total processor load
# };
# Periodically upload current wallpaper to remote server
# systemd.user = {
# services."wallpaper" = {
# path = with pkgs; [
# openssh
# rsync
# tailscale
# variety
# ];
# #!! Hostname dependent
# script = ''
# rsync --chown caddy:caddy "$(variety --current)" root@myne:/srv/static/wallpaper.png
# '';
# };
# timers."wallpaper" = {
# wantedBy = [ "timers.target" ];
# timerConfig = {
# OnBootSec = "1m";
# OnUnitActiveSec = "1m";
# };
# };
# };
}

View file

@ -1,7 +1,6 @@
{
config,
inputs,
lib,
pkgs,
...
}: let
@ -30,20 +29,6 @@ in {
};
};
home-manager.users.${config.custom.username} = {
wayland.windowManager.hyprland.settings = {
exec-once = ["${brightnessctl} set 0%"];
device = [
{
name = "pixa3854:00-093a:0274-touchpad";
accel_profile = "adaptive";
sensitivity = 0.3;
}
];
};
};
services.keyd.keyboards.default.settings.main.rightcontrol = "layer(altgr)"; # No Ctrl_R
boot = {
@ -69,4 +54,18 @@ in {
#// "amd_pstate=disable"
];
};
home-manager.users.${config.custom.username} = {
wayland.windowManager.hyprland.settings = {
exec-once = ["${brightnessctl} set 0%"];
device = [
{
name = "pixa3854:00-093a:0274-touchpad";
accel_profile = "adaptive";
sensitivity = 0.3;
}
];
};
};
}

View file

@ -38,10 +38,13 @@ in {
# TODO: Use nobody:nogroup instead when docker allows changing mount ownership
# HACK: Copy with global read-only permissions in container directory which is assumed to be locked down
# https://github.com/moby/moby/issues/2259
systemd.tmpfiles.rules = [
"C ${config.custom.containers.directory}/coturn/coturn.conf 0444 - - - ${
config.age.secrets."${config.custom.profile}/coturn/coturn.conf".path
}"
];
systemd.tmpfiles.settings."10-coturn" = {
"${config.custom.containers.directory}/coturn/coturn.conf" = {
C = {
mode = "0444";
argument = "${config.age.secrets."${config.custom.profile}/coturn/coturn.conf".path}";
};
};
};
};
}

View file

@ -79,7 +79,16 @@ in {
podman-tui
];
systemd.tmpfiles.rules = ["d /containers 0700 root root"]; # Custom directory for containers
systemd.tmpfiles.settings."10-containers" = {
"/containers" = {
d = {
mode = "0700";
user = "root";
group = "root";
};
};
};
users.users.${config.custom.username}.extraGroups = [
(
if cfg.docker

View file

@ -81,6 +81,14 @@ in {
};
#!! Required for correct volume permissions
systemd.tmpfiles.rules = ["z ${config.custom.containers.directory}/netbox/media 0770 999 root"]; # unit:root
systemd.tmpfiles.settings."10-netbox" = {
"${config.custom.containers.directory}/netbox/media" = {
z = {
mode = "0770";
user = "999"; # unit
group = "root";
};
};
};
};
}

View file

@ -272,6 +272,7 @@ in {
then "--scale 140"
else ""
} myndows'')
(key "W" "Super+Ctrl+Shift" "exec" virt-manager)
(key "W" "Super+Shift" "movetoworkspacesilent" "special:vm")
(key "X" "Super" "workspace" "+1")
(key "X" "Super+Shift" "movetoworkspacesilent" "+1")

View file

@ -29,6 +29,7 @@ in {
"plugin:hyprbars:nobar, class:^dev\\.benz\\.walker$"
"plugin:hyprbars:nobar, class:^discord$, title:^Discord Updater$"
"plugin:hyprbars:nobar, class:^dropdown$"
"plugin:hyprbars:nobar, class:^looking-glass-client$"
"plugin:hyprbars:nobar, class:^moe\\.launcher\\..+$"
"plugin:hyprbars:nobar, class:^org\\.gnome\\.Nautilus$, title:^New Folder$"
"plugin:hyprbars:nobar, class:^org\\.gnome\\.NautilusPreviewer$"

View file

@ -246,6 +246,7 @@ in {
];
vm = rules: [
(class "(sdl-|wl|x)freerdp" (rules ++ ["nomaxsize" "tile"]))
(class "looking-glass-client" rules)
(class "org\\.remmina\\.Remmina" (rules ++ ["tile"]))
(class "virt-manager" rules)
];

View file

@ -9,14 +9,17 @@ with lib; let
audio = config.home-manager.users.${config.custom.username}.home.file.".local/bin/audio".source;
clipse = "${pkgs.clipse}/bin/clipse";
firefox-esr = "${config.home-manager.users.${config.custom.username}.programs.firefox.finalPackage}/bin/firefox-esr";
grep = "${pkgs.gnugrep}/bin/grep";
left = config.home-manager.users.${config.custom.username}.home.file.".local/bin/left".source;
loupe = "${pkgs.loupe}/bin/loupe";
modprobe = "${pkgs.kmod}/bin/modprobe";
nautilus = "${pkgs.nautilus}/bin/nautilus";
pkill = "${pkgs.procps}/bin/pkill";
rm = "${pkgs.coreutils}/bin/rm";
sleep = "${pkgs.coreutils}/bin/sleep";
sway-audio-idle-inhibit = "${pkgs.sway-audio-idle-inhibit}/bin/sway-audio-idle-inhibit";
systemctl = "${pkgs.systemd}/bin/systemctl";
virsh = "${config.virtualisation.libvirtd.package}/bin/virsh";
waybar = "${config.home-manager.users.${config.custom.username}.programs.waybar.package}/bin/waybar";
cfg = config.custom.desktops.hyprland.settings;
@ -36,7 +39,7 @@ in {
# https://wiki.hyprland.org/Configuring/Monitors
#?? monitor = NAME, RESOLUTION, POSITION, SCALE
monitor = [
monitor = mkBefore [
", highrr, auto, ${toString config.custom.scale}"
# HACK: Ensure the fallback output has a sane resolution
@ -66,8 +69,7 @@ in {
# https://wiki.hyprland.org/Configuring/Keywords/#executing
exec-once =
optionals config.custom.wallpaper ["wallpaper"]
++ [
[
sway-audio-idle-inhibit # Inhibit idle while audio is playing
"${audio} --init" # Enforce audio profile state
"${rm} ~/.cache/walker/clipboard.gob" # Clear clipboard history
@ -77,6 +79,13 @@ in {
# HACK: Launch hidden GTK windows to reduce startup time
"[workspace special:hidden silent] ${loupe}"
"[workspace special:hidden silent] ${nautilus}"
]
++ optionals config.custom.wallpaper [
"wallpaper"
]
# HACK: Delay driver initialization to work around reset issues
++ optionals config.custom.settings.vm.passthrough.init [
"${virsh} list | ${grep} ${config.custom.settings.vm.passthrough.guest} || sudo ${modprobe} ${config.custom.settings.vm.passthrough.driver}"
];
# https://wiki.hyprland.org/Configuring/Variables/#xwayland
@ -253,6 +262,10 @@ in {
devices = names: attrs: map (name: {inherit name;} // attrs) names;
in
flatten [
(devices ["compx-2.4g-receiver-mouse"] {
accel_profile = "custom 1 0 1 10 20";
})
(devices ["kensington-orbit-wireless-tb-mouse" "orbit-bt5.0-mouse"] {
accel_profile = "adaptive";
left_handed = true;
@ -270,7 +283,7 @@ in {
sensitivity = -0.7;
})
(devices ["razer-razer-viper-ultimate" "razer-razer-viper-ultimate-dongle"] {
(devices ["razer-razer-viper-ultimate" "razer-razer-viper-ultimate-dongle" "razer-razer-viper-ultimate-dongle-1"] {
sensitivity = -0.7;
})

View file

@ -10,6 +10,14 @@ in {
config = mkIf cfg.enable {
# Set /mnt permissions
systemd.tmpfiles.rules = ["z /mnt 0755 root root"];
systemd.tmpfiles.settings."10-mnt" = {
"/mnt" = {
z = {
mode = "0755";
user = "root";
group = "root";
};
};
};
};
}

View file

@ -11,9 +11,20 @@ in {
config = mkIf cfg.enable {
# https://www.freedesktop.org/software/systemd/man/latest/tmpfiles.d.html
# Create NixOS configuration directory and set permissions
systemd.tmpfiles.rules = [
"d /etc/nixos 0755 myned root"
"Z /etc/nixos - myned root" # Recursively set owner
];
systemd.tmpfiles.settings."10-nixos" = {
"/etc/nixos" = {
d = {
mode = "0755";
user = config.custom.username;
group = "root";
};
#!! Recursive
Z = {
user = config.custom.username;
group = "root";
};
};
};
};
}

View file

@ -214,6 +214,7 @@ in {
"browser.search.widget.inNavBar" = locked false;
"browser.startup.homepage" = locked "about:home";
"browser.startup.page" = locked 3; # Previous session
"browser.tabs.allowTabDetach" = locked false;
"browser.tabs.closeTabByDblclick" = locked true;
"browser.tabs.closeWindowWithLastTab" = locked false;
"browser.tabs.insertAfterCurrent" = locked false;
@ -230,6 +231,7 @@ in {
"extensions.formautofill.creditCards.enabled" = locked false;
"general.autoScroll" = locked false;
"general.smoothScroll" = locked true;
"gfx.webrender.software" = locked true;
"layers.acceleration.force-enabled" = locked true;
"layout.css.always_underline_links" = locked false;
"layout.css.backdrop-filter.enabled" = locked true;

View file

@ -0,0 +1,107 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.custom.programs.looking-glass;
in {
options.custom.programs.looking-glass = {
enable = mkOption {default = false;};
kvmfr = mkOption {default = true;};
};
config = mkIf cfg.enable {
#!! Imperative libvirt xml configuration
# https://looking-glass.io/
# https://looking-glass.io/docs/B6/install/
# BUG: CPU host-passthrough causes error on VM start
# https://github.com/tianocore/edk2/discussions/4662
#?? <cpu><maxphysaddr mode="passthrough" limit="40"/></cpu>
# https://looking-glass.io/docs/B6/module/#kernel-module
boot = mkIf cfg.kvmfr {
extraModulePackages = [config.boot.kernelPackages.kvmfr];
extraModprobeConfig = "options kvmfr static_size_mb=128";
kernelModules = ["kvmfr"];
};
systemd = {
tmpfiles.settings."10-looking-glass" = {
${
if cfg.kvmfr
then "/dev/kvmfr0"
else "/dev/shm/looking-glass"
} = {
${
if cfg.kvmfr
then "z"
else "f"
} = {
mode = "0660";
user = config.custom.username;
group = "qemu-libvirtd";
};
};
};
# HACK: Remove exclusion of /dev prefix from service so rules take effect for devices
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/boot/systemd/tmpfiles.nix
# https://github.com/NixOS/nixpkgs/commit/e6b66f08a53261cf825817df59d3ccd75ed0eead
services.systemd-tmpfiles-setup.serviceConfig = {
ExecStart = mkForce "systemd-tmpfiles --create --remove --boot --exclude-prefix=/sysroot";
};
};
# https://looking-glass.io/docs/B6/module/#libvirt
virtualisation.libvirtd.qemu.verbatimConfig = mkIf cfg.kvmfr ''
cgroup_device_acl = [
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
"/dev/rtc", "/dev/hpet", "/dev/vfio/vfio",
"/dev/kvmfr0"
]
# Default configuration
namespaces = []
'';
home-manager.users.${config.custom.username} = {
# BUG: Crashes when reconnecting to spice channel
programs.looking-glass-client = {
enable = true;
# https://looking-glass.io/docs/B6/usage/#all-command-line-options
settings = {
app = {
shmFile =
if cfg.kvmfr
then "/dev/kvmfr0"
else "/dev/shm/looking-glass";
};
input = {
grabKeyboard = false;
ignoreWindowsKeys = true;
};
spice = {
# BUG: SPICE audio causes disconnections, remove with QEMU >= 9.1.2
# https://gitlab.com/qemu-project/qemu/-/commit/8d9c6f6fa9eebd09ad8d0b4b4de4a0ec57e756d1
audio = false;
};
win = {
borderless = true;
fullScreen = true;
quickSplash = true;
size = "${toString (config.custom.width / 2)}x${toString (config.custom.height / 2)}";
uiFont = config.custom.font.monospace;
uiSize = 24;
};
};
};
};
};
}

View file

@ -94,6 +94,11 @@ in {
libnotify
systemd
])
(bash "iommu" [
coreutils
findutils
pciutils
])
(bash "launch" [
argc
coreutils

View file

@ -0,0 +1,12 @@
#! /usr/bin/env bash
# https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Ensuring_that_the_groups_are_valid
shopt -s nullglob
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
echo "IOMMU Group ${g##*/}:"
for d in "$g"/devices/*; do
echo -e "\t$(lspci -nns "${d##*/}")"
done
done

View file

@ -35,10 +35,20 @@ in {
};
# Serve static files
systemd.tmpfiles.rules = [
"d /srv/static - caddy caddy"
"Z /srv/static - caddy caddy"
];
systemd.tmpfiles.settings."10-caddy" = {
"/srv/static" = {
d = {
user = "caddy";
group = "caddy";
};
#!! Recursive
Z = {
user = "caddy";
group = "caddy";
};
};
};
# https://wiki.nixos.org/wiki/Firewall
# https://github.com/coturn/coturn/blob/master/docker/coturn/README.md

View file

@ -27,6 +27,7 @@ in {
SYNC.path = config.custom.sync;
global = {
"acl allow execute always" = "yes"; # Required for execution on Windows
"allow insecure wide links" = "yes";
"browseable" = "no";
"follow symlinks" = "yes";

View file

@ -157,7 +157,14 @@ in {
systemd = {
# Ensure creation of config directory
tmpfiles.rules = ["d ${cfg.configDir} - ${cfg.user} ${cfg.group}"];
tmpfiles.settings."10-syncthing" = {
${cfg.configDir} = {
d = {
user = cfg.user;
group = cfg.group;
};
};
};
#!! Syncthing needs to start after mounting or there is a risk of file deletion
# https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/networking/syncthing.nix#L646

View file

@ -16,7 +16,7 @@ in {
kernel = mkOption {
default =
if config.custom.full
then pkgs.linuxPackages_6_11
then pkgs.linuxPackages_6_12
else pkgs.linuxPackages;
};
systemd-boot = mkOption {default = config.custom.minimal;};

View file

@ -12,6 +12,7 @@ with lib; {
networking.enable = true;
packages.enable = true;
security.enable = true;
storage.enable = true;
users.enable = true;
})

View file

@ -1,83 +0,0 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.custom.settings.mounts;
in {
options.custom.settings.mounts.enable = mkOption {default = false;};
config = mkIf cfg.enable {
# Enforce permissions for mountpoint directory
systemd.tmpfiles.rules = ["d /mnt/remote 0755 root root"];
#!! FUSE does not support remount, sometimes causing activation errors on switch
# https://github.com/libfuse/libfuse/issues/717
#?? sudo umount /mnt/remote && sudo mount /mnt/remote
# https://wiki.nixos.org/wiki/SSHFS
# https://man.archlinux.org/man/sshfs.1
fileSystems = let
#?? "/mnt/PATH" = remote "PATH" UID GID "UMASK"
remote = path: uid: gid: umask: {
# https://robot.hetzner.com/storage
device = "u415778@u415778.your-storagebox.de:/home/${path}";
fsType = "sshfs";
options = [
"noatime" # Do not modify access time
"reconnect" # Gracefully handle network issues
"default_permissions" # Check local permissions
"allow_other" # Grant other users access
"umask=${umask}" # Set permissions mask
"uid=${toString uid}" # Set user id
"gid=${toString gid}" # Set group id
"idmap=user" # Map local users to remote
"transform_symlinks" # Convert absolute symlinks to relative
"compression=no" # Save CPU cycles at the cost of transfer speed
"port=23"
"IdentityFile=/etc/ssh/id_ed25519" # !! SSH key configured imperatively
"ServerAliveInterval=15" # Prevent application hangs on reconnect
];
};
in {
# Use umask to set sshfs permissions
#!! Up to 10 simultaneous connections with Hetzner
#?? docker compose exec CONTAINER cat /etc/passwd
"/mnt/remote/conduwuit" = remote "conduwuit" 300 300 "0077"; # conduit:conduit @ 0700
#// "/mnt/remote/nextcloud" = remote "nextcloud" 33 33 "0007"; # www-data:www-data @ 0700
"/mnt/remote/syncthing" = remote "syncthing" 237 237 "0077"; # syncthing:syncthing @ 0700
};
# https://wiki.nixos.org/wiki/Rclone
# https://docs.hetzner.com/robot/storage-box/access/access-ssh-rsync-borg/#rclone
#!! SSH keys configured imperatively
#!! rclone attempts to write to immutable config; need to manually merge changes
# https://github.com/rclone/rclone/issues/3655
# TODO: Attempt to use rclone after daemon is fixed
# https://github.com/rclone/rclone/issues/5664
# environment.etc."rclone.conf".text = ''
# [remote]
# type = sftp
# host = u415778.your-storagebox.de
# user = u415778
# port = 23
# key_file = /etc/ssh/id_ed25519
# shell_type = unix
# '';
# fileSystems."/mnt/remote" = {
# device = "remote:/home";
# fsType = "rclone";
# options = [
# "nodev"
# "nofail"
# "reconnect"
# "args2env" # Pass secrets as environment variables
# "default_permissions"
# "config=/etc/rclone.conf"
# ];
# };
};
}

View file

@ -49,6 +49,9 @@ in {
kdiskmark # Must be system package for polkit
### CLI applications
mesa-demos # <glx|vk>gears
vulkan-tools # vkcube
# https://github.com/sonic2kk/steamtinkerlaunch
# TODO: Remove when v14 released on nixpkgs
# https://github.com/sonic2kk/steamtinkerlaunch/issues/992

View file

@ -1,6 +1,7 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
@ -25,5 +26,21 @@ in {
'';
};
};
environment.shellAliases = {
# Sudo confirmation prompt
sudo = pkgs.writeShellScript "sudo" ''
read -p "Execute as root? [Y/n] "
case "$REPLY" in
"" | [Yy])
command sudo "$@"
;;
*)
exit 1
;;
esac
'';
};
};
}

View file

@ -0,0 +1,80 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.custom.settings.storage;
in {
options.custom.settings.storage = {
enable = mkOption {default = false;};
mnt = mkOption {default = [];};
remote = mkOption {default = false;};
};
config = mkIf cfg.enable {
# Enforce permissions for mountpoint directory
systemd.tmpfiles.settings."10-storage" = {
"/mnt/remote" = {
d = {
mode = "0755";
user = "root";
group = "root";
};
};
};
#!! FUSE does not support remount, sometimes causing activation errors on switch
# https://github.com/libfuse/libfuse/issues/717
#?? sudo umount /mnt/remote && sudo mount /mnt/remote
# https://wiki.nixos.org/wiki/SSHFS
# https://man.archlinux.org/man/sshfs.1
fileSystems = let
#?? "/mnt/PATH" = remote "PATH" UID GID "UMASK"
remote = path: uid: gid: umask: {
# https://robot.hetzner.com/storage
device = "u415778@u415778.your-storagebox.de:/home/${path}";
fsType = "sshfs";
options = [
"noatime" # Do not modify access time
"reconnect" # Gracefully handle network issues
"default_permissions" # Check local permissions
"allow_other" # Grant other users access
"umask=${umask}" # Set permissions mask
"uid=${toString uid}" # Set user id
"gid=${toString gid}" # Set group id
"idmap=user" # Map local users to remote
"transform_symlinks" # Convert absolute symlinks to relative
"compression=no" # Save CPU cycles at the cost of transfer speed
"port=23"
"IdentityFile=/etc/ssh/id_ed25519" # !! SSH key configured imperatively
"ServerAliveInterval=15" # Prevent application hangs on reconnect
];
};
in
# Map list of disk labels to /mnt/LABEL with user defaults
mergeAttrsList (forEach cfg.mnt (label: {
"/mnt/${label}" = {
device = "/dev/disk/by-label/${label}";
options = [
"defaults"
"noatime"
"nofail"
"user"
"exec"
"x-gvfs-show"
];
};
}))
// optionalAttrs cfg.remote {
# Use umask to set sshfs permissions
#!! Up to 10 simultaneous connections with Hetzner
#?? docker compose exec CONTAINER cat /etc/passwd
#// "/mnt/remote/conduwuit" = remote "conduwuit" 300 300 "0077"; # conduit:conduit @ 0700
#// "/mnt/remote/nextcloud" = remote "nextcloud" 33 33 "0007"; # www-data:www-data @ 0700
#// "/mnt/remote/syncthing" = remote "syncthing" 237 237 "0077"; # syncthing:syncthing @ 0700
};
};
}

View file

@ -6,12 +6,24 @@
...
}:
with lib; let
virsh = "${config.virtualisation.libvirtd.package}/bin/virsh";
cfg = config.custom.settings.vm;
in {
options.custom.settings.vm = {
enable = mkOption {default = false;};
libvirt = mkOption {default = true;};
virtualbox = mkOption {default = false;};
passthrough = {
enable = mkOption {default = false;};
driver = mkOption {default = null;}; #?? lspci -k
guest = mkOption {default = null;}; #?? virsh list --all
id = mkOption {default = null;}; #?? lspci -nn
init = mkOption {default = false;};
intel = mkOption {default = false;};
node = mkOption {default = null;}; #?? virsh nodedev-list
};
};
config = mkIf cfg.enable {
@ -23,12 +35,37 @@ in {
onBoot = "ignore";
onShutdown = "shutdown";
# https://libvirt.org/hooks.html
hooks.qemu = {
# Attach/detach GPU for passthrough
passthrough = mkIf cfg.passthrough.enable (pkgs.writeShellScript "passthrough" ''
if [[ "$1" == "${cfg.passthrough.guest}" ]]; then
case "$2" in
prepare)
${virsh} nodedev-detach ${cfg.passthrough.node}
;;
release)
${virsh} nodedev-reattach ${cfg.passthrough.node}
;;
*)
exit
;;
esac
fi
'');
};
qemu = {
swtpm.enable = true; # TPM emulation
# BUG: Windows requires global mountpoint for some applications (\\.\*: instead of *:)
# https://github.com/virtio-win/kvm-guest-drivers-windows/issues/950
# https://virtio-win.github.io/Knowledge-Base/Virtiofs:-Shared-file-system
#// vhostUserPackages = with pkgs; [virtiofsd]; # virtiofs support
# Build OVMF with Windows 11 support
ovmf.packages = [
(pkgs.OVMF.override {
ovmf.packages = with pkgs; [
(OVMF.override {
secureBoot = true;
tpmSupport = true;
})
@ -77,24 +114,42 @@ in {
++ lib.optionals cfg.virtualbox ["vboxusers"];
systemd = mkIf cfg.libvirt {
# Fix resume messages polluting tty
services.libvirt-guests.serviceConfig.StandardOutput = "journal";
services = {
# Fix resume messages polluting tty
libvirt-guests.serviceConfig = {
StandardOutput = "journal";
};
};
tmpfiles.settings."10-vm" = {
# HACK: Manually link image to default directory
"/var/lib/libvirt/images/virtio-win.iso" = {
"L+" = {
argument = "${inputs.virtio-win}";
};
};
tmpfiles.rules = let
firmware = pkgs.runCommandLocal "qemu-firmware" {} ''
mkdir $out
cp ${pkgs.qemu}/share/qemu/firmware/*.json $out
substituteInPlace $out/*.json --replace ${pkgs.qemu} /run/current-system/sw
'';
in [
# HACK: Fix libvirt not automatically locating firmware
# https://github.com/NixOS/nixpkgs/issues/115996#issuecomment-2224296279
# https://libvirt.org/formatdomain.html#bios-bootloader
"L+ /var/lib/qemu/firmware - - - - ${firmware}"
"/var/lib/qemu/firmware" = {
"L+" = {
argument = "${pkgs.runCommandLocal "qemu-firmware" {} ''
mkdir $out
cp ${pkgs.qemu}/share/qemu/firmware/*.json $out
substituteInPlace $out/*.json --replace ${pkgs.qemu} /run/current-system/sw
''}";
};
};
};
};
# HACK: Manually link image to default directory
"L+ /var/lib/libvirt/images/virtio-win.iso - - - - ${inputs.virtio-win}"
];
boot = mkIf cfg.passthrough.enable {
# https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Isolating_the_GPU
blacklistedKernelModules = mkIf cfg.passthrough.init [cfg.passthrough.driver];
# https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Enabling_IOMMU
kernelParams = mkIf cfg.passthrough.intel ["intel_iommu=on"];
};
};
}

View file

@ -3,11 +3,7 @@
full = true;
profile = "desktop";
wallpaper = true;
programs.looking-glass.enable = true;
services.power-profiles-daemon.enable = true;
programs.anime-game-launcher = {
enable = true;
genshin-impact = true;
};
};
}

View file

@ -44,6 +44,7 @@
];
};
# TODO: Setup netdata
# netdata = {
# enable = true;
# parent = true;
@ -59,10 +60,5 @@
group = "syncthing";
};
};
# settings = {
# mounts.enable = true;
# #// users.myned.linger = true;
# };
};
}