phase 2: move host files to hosts/{mreow,yarn,muffin}/
This commit is contained in:
60
hosts/mreow/default.nix
Normal file
60
hosts/mreow/default.nix
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
username,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./common.nix
|
||||
./disk_mreow.nix
|
||||
|
||||
inputs.nixos-hardware.nixosModules.framework-amd-ai-300-series
|
||||
];
|
||||
|
||||
hardware.framework.laptop13.audioEnhancement.rawDeviceName =
|
||||
lib.mkDefault "alsa_output.pci-0000_c1_00.6.analog-stereo";
|
||||
|
||||
# PST
|
||||
# time.timeZone = lib.mkForce "America/Los_Angeles";
|
||||
|
||||
# weird hack to get swaylock working? idk, if you don't put this here, password entry doesnt work
|
||||
# if I move to another lock screen program, i will have to replace `swaylock`
|
||||
security.pam.services.swaylock = { };
|
||||
|
||||
# Kernel-level power tuning. These are boot-time / module-load-time settings
|
||||
# that power-profiles-daemon (in common.nix) does not manage. ppd handles
|
||||
# governor and EPP at runtime; these cover everything else.
|
||||
boot.kernelParams = [
|
||||
# Disable NMI watchdog. Eliminates periodic perf-counter interrupts
|
||||
# across all cores (~1 W). Kernel softlockup watchdog remains active.
|
||||
"nmi_watchdog=0"
|
||||
|
||||
# Route kernel work items to already-busy CPUs rather than waking idle
|
||||
# ones. Reduces C-state exit frequency -- significant on battery where
|
||||
# cores idle often.
|
||||
"workqueue.power_efficient=1"
|
||||
];
|
||||
|
||||
boot.kernel.sysctl."kernel.nmi_watchdog" = 0;
|
||||
|
||||
# Power-gate the HDA codec between audio activity. 1-second inactivity
|
||||
# timeout; controller powers down fully. Wakes transparently on next
|
||||
# audio event -- no audible artifacts on Framework 13 AMD.
|
||||
boot.extraModprobeConfig = ''
|
||||
options snd_hda_intel power_save=1 power_save_controller=Y
|
||||
'';
|
||||
|
||||
# Greetd display manager
|
||||
services.greetd = {
|
||||
enable = true;
|
||||
settings = {
|
||||
default_session = {
|
||||
command = "${lib.getExe pkgs.tuigreet} --time";
|
||||
user = username;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
53
hosts/mreow/disk.nix
Normal file
53
hosts/mreow/disk.nix
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
device = "/dev/disk/by-path/pci-0000:01:00.0-nvme-1";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
luks = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "luks";
|
||||
name = "crypted";
|
||||
passwordFile = "${./secrets/disk-password}";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "f2fs";
|
||||
mountpoint = "/";
|
||||
extraArgs = [
|
||||
"-O"
|
||||
"extra_attr,inode_checksum,sb_checksum,compression"
|
||||
];
|
||||
mountOptions = [
|
||||
"compress_algorithm=zstd:6,compress_chksum,atgc,gc_merge,lazytime,nodiscard"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
33
hosts/mreow/home.nix
Normal file
33
hosts/mreow/home.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
homeDirectory,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./gui.nix
|
||||
./desktop.nix
|
||||
./progs/borg.nix
|
||||
|
||||
# effects headphones too
|
||||
# ./progs/framework-13-easyeffects.nix
|
||||
];
|
||||
|
||||
# media controls
|
||||
systemd.user.services.mpris-proxy = {
|
||||
Unit.Description = "Mpris proxy";
|
||||
Install.After = [
|
||||
"network.target"
|
||||
"sound.target"
|
||||
];
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
Service.ExecStart = "${pkgs.bluez}/bin/mpris-proxy";
|
||||
};
|
||||
|
||||
programs.niri.settings.outputs = {
|
||||
"BOE 0x095F Unknown" = {
|
||||
scale = 1.5;
|
||||
};
|
||||
};
|
||||
}
|
||||
328
hosts/muffin/default.nix
Normal file
328
hosts/muffin/default.nix
Normal file
@@ -0,0 +1,328 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
hostname,
|
||||
username,
|
||||
eth_interface,
|
||||
service_configs,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./modules/hardware.nix
|
||||
./modules/zfs.nix
|
||||
./modules/impermanence.nix
|
||||
./modules/usb-secrets.nix
|
||||
./modules/age-secrets.nix
|
||||
./modules/secureboot.nix
|
||||
./modules/no-rgb.nix
|
||||
./modules/security.nix
|
||||
./modules/ntfy-alerts.nix
|
||||
./modules/power.nix
|
||||
|
||||
./services/postgresql.nix
|
||||
./services/jellyfin
|
||||
./services/caddy
|
||||
./services/immich.nix
|
||||
./services/gitea.nix
|
||||
./services/gitea-actions-runner.nix
|
||||
./services/minecraft.nix
|
||||
|
||||
./services/wg.nix
|
||||
./services/qbittorrent.nix
|
||||
./services/bitmagnet.nix
|
||||
|
||||
./services/arr/prowlarr.nix
|
||||
./services/arr/sonarr.nix
|
||||
./services/arr/radarr.nix
|
||||
./services/arr/bazarr.nix
|
||||
./services/arr/jellyseerr.nix
|
||||
./services/arr/recyclarr.nix
|
||||
./services/arr/arr-search.nix
|
||||
./services/arr/torrent-audit.nix
|
||||
./services/arr/init.nix
|
||||
|
||||
./services/soulseek.nix
|
||||
|
||||
# ./services/llama-cpp.nix
|
||||
./services/trilium.nix
|
||||
|
||||
./services/ups.nix
|
||||
|
||||
./services/grafana
|
||||
|
||||
./services/bitwarden.nix
|
||||
./services/firefox-syncserver.nix
|
||||
|
||||
./services/matrix
|
||||
|
||||
./services/monero
|
||||
|
||||
./services/graphing-calculator.nix
|
||||
|
||||
./services/ssh.nix
|
||||
|
||||
./services/syncthing.nix
|
||||
|
||||
./services/ntfy
|
||||
|
||||
./services/mollysocket.nix
|
||||
|
||||
./services/harmonia.nix
|
||||
|
||||
./services/ddns-updater.nix
|
||||
];
|
||||
|
||||
# Hosts entries for CI/CD deploy targets
|
||||
networking.hosts."192.168.1.50" = [ "server-public" ];
|
||||
networking.hosts."192.168.1.223" = [ "desktop" ];
|
||||
|
||||
# SSH known_hosts for CI runner (pinned host keys)
|
||||
environment.etc."ci-known-hosts".text = ''
|
||||
server-public ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu
|
||||
192.168.1.50 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu
|
||||
git.sigkill.computer ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu
|
||||
git.gardling.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu
|
||||
'';
|
||||
|
||||
services.kmscon.enable = true;
|
||||
|
||||
# Disable serial getty on ttyS0 to prevent dmesg warnings
|
||||
systemd.services."serial-getty@ttyS0".enable = false;
|
||||
|
||||
# srvos enables vim, i don't want to use vim, disable it here:
|
||||
programs.vim = {
|
||||
defaultEditor = false;
|
||||
}
|
||||
// lib.optionalAttrs (options.programs.vim ? enable) {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/issues/101459#issuecomment-758306434
|
||||
security.pam.loginLimits = [
|
||||
{
|
||||
domain = "*";
|
||||
type = "soft";
|
||||
item = "nofile";
|
||||
value = "4096";
|
||||
}
|
||||
];
|
||||
|
||||
nix = {
|
||||
# optimize the store
|
||||
optimise.automatic = true;
|
||||
|
||||
# garbage collection
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 7d";
|
||||
};
|
||||
};
|
||||
|
||||
# Intel Arc A380 (DG2, 56a5) uses the i915 driver on kernel 6.12.
|
||||
# The xe driver's iHD media driver integration has buffer mapping
|
||||
# failures on this GPU/kernel combination. i915 works correctly for
|
||||
# VAAPI transcode as long as ASPM deep states are disabled for the
|
||||
# GPU (see modules/power.nix).
|
||||
hardware.intelgpu.driver = "i915";
|
||||
|
||||
# Per-service 2MB hugepage budget calculated in service-configs.nix.
|
||||
boot.kernel.sysctl."vm.nr_hugepages" = service_configs.hugepages_2m.total_pages;
|
||||
|
||||
boot = {
|
||||
# 6.12 LTS until 2027-03. Kernel 6.18 causes a reproducible ZFS deadlock
|
||||
# in dbuf_evict due to page allocator changes (__free_frozen_pages).
|
||||
# https://github.com/openzfs/zfs/issues/18426
|
||||
kernelPackages = pkgs.linuxPackages_6_12;
|
||||
|
||||
loader = {
|
||||
# Use the systemd-boot EFI boot loader.
|
||||
# Disabled: ASRock B550M Pro4 AMI UEFI hangs on POST when NixOS
|
||||
# writes EFI variables (NVRAM corruption). Lanzaboote boot entries
|
||||
# are discovered via BLS Type #2 on the ESP, so this is not needed.
|
||||
efi.canTouchEfiVariables = false;
|
||||
|
||||
# 1s timeout
|
||||
timeout = 1;
|
||||
};
|
||||
|
||||
initrd = {
|
||||
compressor = "zstd";
|
||||
supportedFilesystems = [ "f2fs" ];
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
"issue".text = "";
|
||||
};
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "America/New_York";
|
||||
|
||||
hardware.graphics = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; [
|
||||
libva-vdpau-driver
|
||||
intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
|
||||
vpl-gpu-rt # QSV on 11th gen or newer
|
||||
];
|
||||
};
|
||||
|
||||
#fwupd for updating firmware
|
||||
services.fwupd = {
|
||||
enable = true;
|
||||
extraRemotes = [ "lvfs-testing" ];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helix
|
||||
lm_sensors
|
||||
bottom
|
||||
htop
|
||||
|
||||
doas-sudo-shim
|
||||
neofetch
|
||||
|
||||
borgbackup
|
||||
smartmontools
|
||||
|
||||
ripgrep
|
||||
|
||||
intel-gpu-tools
|
||||
iotop
|
||||
iftop
|
||||
|
||||
tmux
|
||||
|
||||
wget
|
||||
|
||||
powertop
|
||||
|
||||
lsof
|
||||
|
||||
reflac
|
||||
|
||||
pfetch-rs
|
||||
|
||||
sbctl
|
||||
|
||||
# add `skdump`
|
||||
libatasmart
|
||||
];
|
||||
|
||||
networking = {
|
||||
nameservers = [
|
||||
"1.1.1.1"
|
||||
"9.9.9.9"
|
||||
];
|
||||
|
||||
hostName = hostname;
|
||||
hostId = "0f712d56";
|
||||
firewall.enable = true;
|
||||
|
||||
useDHCP = false;
|
||||
|
||||
# Disabled because of Jellyfin (various issues)
|
||||
enableIPv6 = false;
|
||||
|
||||
interfaces.${eth_interface} = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.1.50";
|
||||
# address = "10.1.1.102";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
ipv6.addresses = [
|
||||
{
|
||||
address = "fe80::9e6b:ff:fe4d:abb";
|
||||
prefixLength = 64;
|
||||
}
|
||||
];
|
||||
};
|
||||
defaultGateway = {
|
||||
#address = "10.1.1.1";
|
||||
address = "192.168.1.1";
|
||||
interface = eth_interface;
|
||||
};
|
||||
# TODO! fix this
|
||||
# defaultGateway6 = {
|
||||
# address = "fe80::/64";
|
||||
# interface = eth_interface;
|
||||
# };
|
||||
};
|
||||
|
||||
users.groups.${service_configs.media_group} = { };
|
||||
|
||||
users.users.gitea-runner = {
|
||||
isSystemUser = true;
|
||||
group = "gitea-runner";
|
||||
home = "/var/lib/gitea-runner";
|
||||
description = "Gitea Actions CI runner";
|
||||
};
|
||||
users.groups.gitea-runner = { };
|
||||
|
||||
users.users.${username} = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"video"
|
||||
"render"
|
||||
service_configs.media_group
|
||||
];
|
||||
hashedPasswordFile = config.age.secrets.hashedPass.path;
|
||||
};
|
||||
|
||||
# https://nixos.wiki/wiki/Fish#Setting_fish_as_your_shell
|
||||
programs.fish.enable = true;
|
||||
programs.bash = {
|
||||
interactiveShellInit = ''
|
||||
if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
|
||||
then
|
||||
shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
|
||||
exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
security = {
|
||||
#lets use doas and not sudo!
|
||||
doas.enable = true;
|
||||
sudo.enable = false;
|
||||
# Configure doas
|
||||
doas.extraRules = [
|
||||
{
|
||||
users = [ username ];
|
||||
keepEnv = true;
|
||||
persist = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.murmur = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
welcometext = "meow meow meow meow meow :3 xd";
|
||||
password = "$MURMURD_PASSWORD";
|
||||
environmentFile = config.age.secrets.murmur-password-env.path;
|
||||
port = service_configs.ports.public.murmur.port;
|
||||
};
|
||||
|
||||
# services.botamusique = {
|
||||
# enable = true;
|
||||
# settings = {
|
||||
# server = {port = config.services.murmur.port;
|
||||
# password = config.services.murmur.password;
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
|
||||
# systemd.tmpfiles.rules = [
|
||||
# "Z /tank/music 775 ${username} users"
|
||||
# ];
|
||||
|
||||
system.stateVersion = "24.11";
|
||||
}
|
||||
59
hosts/muffin/disk.nix
Normal file
59
hosts/muffin/disk.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
imports = [
|
||||
inputs.disko.nixosModules.disko
|
||||
];
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
type = "EF00";
|
||||
size = "500M";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
persistent = {
|
||||
size = "20G";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "f2fs";
|
||||
mountpoint = "/persistent";
|
||||
};
|
||||
};
|
||||
nix = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "f2fs";
|
||||
mountpoint = "/nix";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
nodev = {
|
||||
"/" = {
|
||||
fsType = "tmpfs";
|
||||
mountOptions = [
|
||||
"defaults"
|
||||
"size=2G"
|
||||
"mode=755"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems."/persistent".neededForBoot = true;
|
||||
fileSystems."/nix".neededForBoot = true;
|
||||
|
||||
}
|
||||
62
hosts/muffin/hardware.nix
Normal file
62
hosts/muffin/hardware.nix
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
service_configs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
hddTuneIosched = pkgs.writeShellScript "hdd-tune-iosched" ''
|
||||
# Called by udev with the partition kernel name (e.g. sdb1).
|
||||
# Derives the parent disk and applies mq-deadline iosched params.
|
||||
parent=''${1%%[0-9]*}
|
||||
dev="/sys/block/$parent"
|
||||
[ -d "$dev/queue/iosched" ] || exit 0
|
||||
echo 500 > "$dev/queue/iosched/read_expire"
|
||||
echo 15000 > "$dev/queue/iosched/write_expire"
|
||||
echo 128 > "$dev/queue/iosched/fifo_batch"
|
||||
echo 16 > "$dev/queue/iosched/writes_starved"
|
||||
echo 4096 > "$dev/queue/max_sectors_kb" 2>/dev/null || true
|
||||
'';
|
||||
in
|
||||
{
|
||||
boot.initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"ahci"
|
||||
"usb_storage"
|
||||
"usbhid"
|
||||
"sd_mod"
|
||||
];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
swapDevices = [ ];
|
||||
|
||||
hardware.cpu.amd.updateMicrocode = true;
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
|
||||
# HDD I/O tuning for torrent seeding workload (high-concurrency random reads)
|
||||
# sharing the pool with latency-sensitive sequential reads (Jellyfin playback).
|
||||
#
|
||||
# mq-deadline sorts requests into elevator sweeps, reducing seek distance.
|
||||
# read_expire=500ms keeps reads bounded so a Jellyfin segment can't queue for
|
||||
# seconds behind a torrent burst; write_expire=15s lets the scheduler batch
|
||||
# writes for coalescence (torrent writes are async and tolerate delay).
|
||||
# The bulk of read coalescence already happens above the scheduler via ZFS
|
||||
# aggregation (zfs_vdev_aggregation_limit=4M, read_gap_limit=128K,
|
||||
# async_read_max=32), so the scheduler deadline only needs to be large enough
|
||||
# to keep the elevator sweep coherent -- 500ms is plenty on rotational disks.
|
||||
# fifo_batch=128 keeps sweeps long; writes_starved=16 heavily favors reads.
|
||||
# 4 MiB readahead matches libtorrent piece extent affinity for sequential prefetch.
|
||||
#
|
||||
# The NixOS ZFS module hardcodes a udev rule that forces scheduler="none" on all
|
||||
# ZFS member partitions' parent disks (on both add AND change events). We counter
|
||||
# it with lib.mkAfter so our rule appears after theirs in 99-local.rules — our
|
||||
# rule matches the same partition events and sets mq-deadline back, then a RUN
|
||||
# script applies the iosched params. Only targets rotational, non-removable disks
|
||||
# (i.e. HDDs, not SSDs or USB).
|
||||
services.udev.extraRules = lib.mkAfter ''
|
||||
ACTION=="add|change", KERNEL=="sd[a-z]*[0-9]*", ENV{ID_FS_TYPE}=="zfs_member", ATTR{../queue/rotational}=="1", ATTR{../removable}=="0", ATTR{../queue/scheduler}="mq-deadline", ATTR{../queue/read_ahead_kb}="4096", ATTR{../queue/nr_requests}="512", RUN+="${hddTuneIosched} %k"
|
||||
'';
|
||||
}
|
||||
31
hosts/muffin/home.nix
Normal file
31
hosts/muffin/home.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
home.stateVersion = "24.11";
|
||||
programs.fish = {
|
||||
enable = true;
|
||||
|
||||
interactiveShellInit = ''
|
||||
# disable greeting
|
||||
set fish_greeting
|
||||
|
||||
# pfetch on shell start (disable pkgs because of execution time)
|
||||
PF_INFO="ascii title os host kernel uptime memory editor wm" ${lib.getExe pkgs.pfetch-rs}
|
||||
'';
|
||||
|
||||
shellAliases =
|
||||
let
|
||||
eza = "${lib.getExe pkgs.eza} --color=always --group-directories-first";
|
||||
in
|
||||
{
|
||||
# from DistroTube's dot files: Changing "ls" to "eza"
|
||||
ls = "${eza} -al";
|
||||
la = "${eza} -a";
|
||||
ll = "${eza} -l";
|
||||
lt = "${eza} -aT";
|
||||
};
|
||||
};
|
||||
}
|
||||
364
hosts/muffin/service-configs.nix
Normal file
364
hosts/muffin/service-configs.nix
Normal file
@@ -0,0 +1,364 @@
|
||||
rec {
|
||||
zpool_ssds = "tank";
|
||||
zpool_hdds = "hdds";
|
||||
torrents_path = "/torrents";
|
||||
services_dir = "/services";
|
||||
music_dir = "/${zpool_ssds}/music";
|
||||
media_group = "media";
|
||||
|
||||
cpu_arch = "znver3";
|
||||
|
||||
ports = {
|
||||
# Ports exposed to the internet. The flake asserts every public port
|
||||
# appears in the corresponding firewall allow-list (TCP, UDP, or both).
|
||||
public = {
|
||||
http = {
|
||||
port = 80;
|
||||
proto = "tcp";
|
||||
};
|
||||
https = {
|
||||
port = 443;
|
||||
proto = "both";
|
||||
}; # HTTP/3 QUIC
|
||||
minecraft = {
|
||||
port = 25565;
|
||||
proto = "tcp";
|
||||
};
|
||||
syncthing_protocol = {
|
||||
port = 22000;
|
||||
proto = "both";
|
||||
}; # QUIC
|
||||
syncthing_discovery = {
|
||||
port = 21027;
|
||||
proto = "udp";
|
||||
};
|
||||
matrix_federation = {
|
||||
port = 8448;
|
||||
proto = "both";
|
||||
}; # HTTP/3 QUIC
|
||||
coturn = {
|
||||
port = 3478;
|
||||
proto = "both";
|
||||
};
|
||||
coturn_tls = {
|
||||
port = 5349;
|
||||
proto = "both";
|
||||
};
|
||||
livekit = {
|
||||
port = 7880;
|
||||
proto = "tcp";
|
||||
};
|
||||
soulseek_listen = {
|
||||
port = 50300;
|
||||
proto = "tcp";
|
||||
};
|
||||
monero = {
|
||||
port = 18080;
|
||||
proto = "tcp";
|
||||
};
|
||||
monero_rpc = {
|
||||
port = 18081;
|
||||
proto = "tcp";
|
||||
}; # restricted public RPC
|
||||
p2pool_p2p = {
|
||||
port = 37889;
|
||||
proto = "tcp";
|
||||
};
|
||||
murmur = {
|
||||
port = 64738;
|
||||
proto = "both";
|
||||
};
|
||||
};
|
||||
|
||||
# Ports bound to localhost / VPN only. The flake asserts none of
|
||||
# these appear in the firewall allow-lists.
|
||||
private = {
|
||||
jellyfin = {
|
||||
port = 8096;
|
||||
proto = "tcp";
|
||||
};
|
||||
torrent = {
|
||||
port = 6011;
|
||||
proto = "tcp";
|
||||
};
|
||||
# Webhook receiver for the Jellyfin-qBittorrent monitor — Jellyfin pushes
|
||||
# playback events here so throttling reacts without waiting for the poll.
|
||||
jellyfin_qbittorrent_monitor_webhook = {
|
||||
port = 9898;
|
||||
proto = "tcp";
|
||||
};
|
||||
bitmagnet = {
|
||||
port = 3333;
|
||||
proto = "tcp";
|
||||
};
|
||||
gitea = {
|
||||
port = 2283;
|
||||
proto = "tcp";
|
||||
};
|
||||
immich = {
|
||||
port = 2284;
|
||||
proto = "tcp";
|
||||
};
|
||||
soulseek_web = {
|
||||
port = 5030;
|
||||
proto = "tcp";
|
||||
};
|
||||
vaultwarden = {
|
||||
port = 8222;
|
||||
proto = "tcp";
|
||||
};
|
||||
syncthing_gui = {
|
||||
port = 8384;
|
||||
proto = "tcp";
|
||||
};
|
||||
matrix = {
|
||||
port = 6167;
|
||||
proto = "tcp";
|
||||
};
|
||||
ntfy = {
|
||||
port = 2586;
|
||||
proto = "tcp";
|
||||
};
|
||||
lk_jwt = {
|
||||
port = 8081;
|
||||
proto = "tcp";
|
||||
};
|
||||
prowlarr = {
|
||||
port = 9696;
|
||||
proto = "tcp";
|
||||
};
|
||||
sonarr = {
|
||||
port = 8989;
|
||||
proto = "tcp";
|
||||
};
|
||||
radarr = {
|
||||
port = 7878;
|
||||
proto = "tcp";
|
||||
};
|
||||
bazarr = {
|
||||
port = 6767;
|
||||
proto = "tcp";
|
||||
};
|
||||
jellyseerr = {
|
||||
port = 5055;
|
||||
proto = "tcp";
|
||||
};
|
||||
monero_zmq = {
|
||||
port = 18083;
|
||||
proto = "tcp";
|
||||
};
|
||||
p2pool_stratum = {
|
||||
port = 3334;
|
||||
proto = "tcp";
|
||||
};
|
||||
firefox_syncserver = {
|
||||
port = 5000;
|
||||
proto = "tcp";
|
||||
};
|
||||
mollysocket = {
|
||||
port = 8020;
|
||||
proto = "tcp";
|
||||
};
|
||||
grafana = {
|
||||
port = 3000;
|
||||
proto = "tcp";
|
||||
};
|
||||
prometheus = {
|
||||
port = 9090;
|
||||
proto = "tcp";
|
||||
};
|
||||
prometheus_node = {
|
||||
port = 9100;
|
||||
proto = "tcp";
|
||||
};
|
||||
prometheus_apcupsd = {
|
||||
port = 9162;
|
||||
proto = "tcp";
|
||||
};
|
||||
llama_cpp = {
|
||||
port = 6688;
|
||||
proto = "tcp";
|
||||
};
|
||||
trilium = {
|
||||
port = 8787;
|
||||
proto = "tcp";
|
||||
};
|
||||
jellyfin_exporter = {
|
||||
port = 9594;
|
||||
proto = "tcp";
|
||||
};
|
||||
qbittorrent_exporter = {
|
||||
port = 9561;
|
||||
proto = "tcp";
|
||||
};
|
||||
igpu_exporter = {
|
||||
port = 9563;
|
||||
proto = "tcp";
|
||||
};
|
||||
prometheus_zfs = {
|
||||
port = 9134;
|
||||
proto = "tcp";
|
||||
};
|
||||
harmonia = {
|
||||
port = 5500;
|
||||
proto = "tcp";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
https = {
|
||||
certs = services_dir + "/http_certs";
|
||||
domain = "sigkill.computer";
|
||||
old_domain = "gardling.com"; # Redirect traffic from old domain
|
||||
};
|
||||
|
||||
gitea = {
|
||||
dir = services_dir + "/gitea";
|
||||
domain = "git.${https.domain}";
|
||||
};
|
||||
|
||||
postgres = {
|
||||
socket = "/run/postgresql";
|
||||
dataDir = services_dir + "/sql";
|
||||
shared_buffers_m = 128; # PostgreSQL default; update if you change shared_buffers
|
||||
};
|
||||
|
||||
immich = {
|
||||
dir = services_dir + "/immich";
|
||||
};
|
||||
|
||||
minecraft = {
|
||||
parent_dir = services_dir + "/minecraft";
|
||||
server_name = "main";
|
||||
memory = {
|
||||
heap_size_m = 4000;
|
||||
large_page_size_m = 2;
|
||||
};
|
||||
};
|
||||
|
||||
torrent = {
|
||||
SavePath = torrents_path;
|
||||
TempPath = torrents_path + "/incomplete";
|
||||
categories = {
|
||||
anime = torrents_path + "/anime";
|
||||
archive = torrents_path + "/archive";
|
||||
audiobooks = torrents_path + "/audiobooks";
|
||||
books = torrents_path + "/books";
|
||||
games = torrents_path + "/games";
|
||||
movies = torrents_path + "/movies";
|
||||
music = torrents_path + "/music";
|
||||
musicals = torrents_path + "/musicals";
|
||||
tvshows = torrents_path + "/tvshows";
|
||||
};
|
||||
};
|
||||
|
||||
jellyfin = {
|
||||
dataDir = services_dir + "/jellyfin";
|
||||
cacheDir = services_dir + "/jellyfin_cache";
|
||||
};
|
||||
|
||||
slskd = rec {
|
||||
base = "/var/lib/slskd";
|
||||
downloads = base + "/downloads";
|
||||
incomplete = base + "/incomplete";
|
||||
};
|
||||
|
||||
vaultwarden = {
|
||||
path = "/var/lib/vaultwarden";
|
||||
};
|
||||
|
||||
monero = {
|
||||
dataDir = services_dir + "/monero";
|
||||
};
|
||||
|
||||
p2pool = {
|
||||
dataDir = services_dir + "/p2pool";
|
||||
walletAddress = "49b6NT2k7fQHs8JvF7naUvchYwTQmRpoMMXb1KJTg5UcZVmyPJ7n6jgiH8DrvEsMg5GvMjJqPB1c1PTBAYtUTsbeHe5YMBx";
|
||||
};
|
||||
|
||||
matrix = {
|
||||
dataDir = "/var/lib/continuwuity";
|
||||
domain = "matrix.${https.domain}";
|
||||
};
|
||||
|
||||
ntfy = {
|
||||
domain = "ntfy.${https.domain}";
|
||||
};
|
||||
|
||||
mollysocket = {
|
||||
domain = "mollysocket.${https.domain}";
|
||||
};
|
||||
|
||||
livekit = {
|
||||
domain = "livekit.${https.domain}";
|
||||
};
|
||||
|
||||
syncthing = {
|
||||
dataDir = services_dir + "/syncthing";
|
||||
signalBackupDir = "/${zpool_ssds}/bak/signal";
|
||||
grayjayBackupDir = "/${zpool_ssds}/bak/grayjay";
|
||||
};
|
||||
|
||||
prowlarr = {
|
||||
dataDir = services_dir + "/prowlarr";
|
||||
};
|
||||
|
||||
sonarr = {
|
||||
dataDir = services_dir + "/sonarr";
|
||||
};
|
||||
|
||||
radarr = {
|
||||
dataDir = services_dir + "/radarr";
|
||||
};
|
||||
|
||||
bazarr = {
|
||||
dataDir = services_dir + "/bazarr";
|
||||
};
|
||||
|
||||
jellyseerr = {
|
||||
configDir = services_dir + "/jellyseerr";
|
||||
};
|
||||
|
||||
recyclarr = {
|
||||
dataDir = services_dir + "/recyclarr";
|
||||
};
|
||||
|
||||
firefox_syncserver = {
|
||||
domain = "firefox-sync.${https.domain}";
|
||||
};
|
||||
|
||||
grafana = {
|
||||
dir = services_dir + "/grafana";
|
||||
domain = "grafana.${https.domain}";
|
||||
};
|
||||
|
||||
trilium = {
|
||||
dataDir = services_dir + "/trilium";
|
||||
};
|
||||
|
||||
media = {
|
||||
moviesDir = torrents_path + "/media/movies";
|
||||
tvDir = torrents_path + "/media/tv";
|
||||
};
|
||||
|
||||
# Per-service 2MB hugepage budget.
|
||||
# Each value is the service's hugepage consumption in MB, derived from
|
||||
# its actual memory configuration. The kernel sysctl vm.nr_hugepages
|
||||
# is set to total_pages so every service gets what it needs.
|
||||
hugepages_2m = rec {
|
||||
page_size_m = 2;
|
||||
|
||||
# RandomX dataset (2048MB) + cache (256MB) = 2304MB per instance.
|
||||
# Both monerod and p2pool allocate their own full copy via MAP_HUGETLB.
|
||||
randomx_instance_m = 2048 + 256;
|
||||
|
||||
services = {
|
||||
minecraft_m = minecraft.memory.heap_size_m; # JVM heap via -XX:+UseLargePages
|
||||
monerod_m = randomx_instance_m; # block verification dataset
|
||||
p2pool_m = randomx_instance_m; # mining dataset
|
||||
postgres_m = postgres.shared_buffers_m; # huge_pages = try (default)
|
||||
};
|
||||
|
||||
total_pages = builtins.foldl' (a: b: a + b) 0 (builtins.attrValues services) / page_size_m;
|
||||
};
|
||||
}
|
||||
276
hosts/yarn/default.nix
Normal file
276
hosts/yarn/default.nix
Normal file
@@ -0,0 +1,276 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
username,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./disk_yarn.nix
|
||||
./common.nix
|
||||
./impermanence.nix
|
||||
./no-rgb.nix
|
||||
./vr.nix
|
||||
|
||||
inputs.impermanence.nixosModules.impermanence
|
||||
inputs.jovian-nixos.nixosModules.default
|
||||
];
|
||||
|
||||
fileSystems."/media/games" = {
|
||||
device = "/dev/disk/by-uuid/1878136e-765d-4784-b204-3536ab4fdac8";
|
||||
fsType = "f2fs";
|
||||
options = [ "nofail" ];
|
||||
};
|
||||
|
||||
systemd.targets = {
|
||||
sleep.enable = false;
|
||||
suspend.enable = false;
|
||||
hibernate.enable = false;
|
||||
hybrid-sleep.enable = false;
|
||||
};
|
||||
|
||||
networking.hostId = "abf570f9";
|
||||
|
||||
# Static IP for consistent SSH access
|
||||
networking.networkmanager.ensureProfiles.profiles.enp7s0-static = {
|
||||
connection = {
|
||||
id = "enp7s0-static";
|
||||
type = "ethernet";
|
||||
interface-name = "enp7s0";
|
||||
autoconnect = true;
|
||||
};
|
||||
ipv4 = {
|
||||
method = "manual";
|
||||
address1 = "192.168.1.223/24,192.168.1.1";
|
||||
dns = "1.1.1.1;9.9.9.9;";
|
||||
};
|
||||
ipv6.method = "disabled";
|
||||
};
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
ports = [ 22 ];
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.${username}.openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4jL6gYOunUlUtPvGdML0cpbKSsPNqQ1jit4E7U1RyH" # laptop
|
||||
];
|
||||
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4jL6gYOunUlUtPvGdML0cpbKSsPNqQ1jit4E7U1RyH" # laptop
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC5ZYN6idL/w/mUIfPOH1i+Q/SQXuzAMQUEuWpipx1Pc ci-deploy@muffin"
|
||||
];
|
||||
|
||||
programs.steam = {
|
||||
remotePlay.openFirewall = true;
|
||||
localNetworkGameTransfers.openFirewall = true;
|
||||
};
|
||||
|
||||
# LACT (Linux AMDGPU Configuration Tool): https://github.com/ilya-zlobintsev/LACT
|
||||
environment.systemPackages = with pkgs; [
|
||||
lact
|
||||
jovian-stubs
|
||||
];
|
||||
systemd.packages = with pkgs; [ lact ];
|
||||
systemd.services.lactd.wantedBy = [ "multi-user.target" ];
|
||||
|
||||
systemd.services.lactd.serviceConfig.ExecStartPre = "${lib.getExe pkgs.bash} -c \"sleep 3s\"";
|
||||
|
||||
# root-level service that applies a pending update. Triggered by
|
||||
# steamos-update (via systemctl start) when the user accepts an update.
|
||||
# Runs as root so it can write the system profile and boot entry.
|
||||
systemd.services.pull-update-apply = {
|
||||
description = "Apply pending NixOS update pulled from binary cache";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = pkgs.writeShellScript "pull-update-apply" ''
|
||||
set -uo pipefail
|
||||
export PATH=${
|
||||
pkgs.lib.makeBinPath [
|
||||
pkgs.curl
|
||||
pkgs.coreutils
|
||||
pkgs.nix
|
||||
]
|
||||
}
|
||||
STORE_PATH=$(curl -sf --max-time 30 "https://nix-cache.sigkill.computer/deploy/yarn" || true)
|
||||
if [ -z "$STORE_PATH" ]; then
|
||||
echo "server unreachable"
|
||||
exit 1
|
||||
fi
|
||||
echo "applying $STORE_PATH"
|
||||
nix-store -r "$STORE_PATH" || { echo "fetch failed"; exit 1; }
|
||||
nix-env -p /nix/var/nix/profiles/system --set "$STORE_PATH" || { echo "profile set failed"; exit 1; }
|
||||
"$STORE_PATH/bin/switch-to-configuration" boot || { echo "boot entry failed"; exit 1; }
|
||||
echo "update applied; reboot required"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Allow primary user to start pull-update-apply.service without a password
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
||||
action.lookup("unit") == "pull-update-apply.service" &&
|
||||
subject.user == "${username}") {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
|
||||
nixpkgs.config.allowUnfreePredicate =
|
||||
pkg:
|
||||
builtins.elem (lib.getName pkg) [
|
||||
"steamdeck-hw-theme"
|
||||
"steam-jupiter-unwrapped"
|
||||
"steam"
|
||||
"steam-original"
|
||||
"steam-unwrapped"
|
||||
"steam-run"
|
||||
];
|
||||
|
||||
# Override jovian-stubs to disable steamos-update kernel check
|
||||
# This prevents Steam from requesting reboots for "system updates"
|
||||
# Steam client updates will still work normally
|
||||
nixpkgs.overlays = [
|
||||
(
|
||||
final: prev:
|
||||
let
|
||||
deploy-url = "https://nix-cache.sigkill.computer/deploy/yarn";
|
||||
|
||||
steamos-update-script = final.writeShellScript "steamos-update" ''
|
||||
export PATH=${
|
||||
final.lib.makeBinPath [
|
||||
final.curl
|
||||
final.coreutils
|
||||
final.systemd
|
||||
]
|
||||
}
|
||||
|
||||
STORE_PATH=$(curl -sf --max-time 30 "${deploy-url}" || true)
|
||||
|
||||
if [ -z "$STORE_PATH" ]; then
|
||||
>&2 echo "[steamos-update] server unreachable"
|
||||
exit 7
|
||||
fi
|
||||
|
||||
CURRENT=$(readlink -f /nix/var/nix/profiles/system)
|
||||
if [ "$CURRENT" = "$STORE_PATH" ]; then
|
||||
>&2 echo "[steamos-update] no update available"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# check-only mode: just report that an update exists
|
||||
if [ "''${1:-}" = "check" ] || [ "''${1:-}" = "--check-only" ]; then
|
||||
>&2 echo "[steamos-update] update available"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# apply: trigger the root-running systemd service to install the update
|
||||
>&2 echo "[steamos-update] applying update..."
|
||||
if systemctl start --wait pull-update-apply.service; then
|
||||
>&2 echo "[steamos-update] update installed, reboot to apply"
|
||||
exit 0
|
||||
else
|
||||
>&2 echo "[steamos-update] apply failed; see 'journalctl -u pull-update-apply'"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in
|
||||
{
|
||||
jovian-stubs = prev.stdenv.mkDerivation {
|
||||
name = "jovian-stubs";
|
||||
dontUnpack = true;
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
ln -s ${steamos-update-script} $out/bin/steamos-update
|
||||
ln -s ${steamos-update-script} $out/bin/steamos-mandatory-update
|
||||
|
||||
# jupiter-initial-firmware-update: no-op (not a real steam deck)
|
||||
cat > $out/bin/jupiter-initial-firmware-update << 'STUB'
|
||||
#!/bin/sh
|
||||
exit 0
|
||||
STUB
|
||||
|
||||
# jupiter-biosupdate: no-op (not a real steam deck)
|
||||
cat > $out/bin/jupiter-biosupdate << 'STUB'
|
||||
#!/bin/sh
|
||||
exit 0
|
||||
STUB
|
||||
|
||||
# steamos-reboot: reboot the system
|
||||
cat > $out/bin/steamos-reboot << 'STUB'
|
||||
#!/bin/sh
|
||||
>&2 echo "[JOVIAN] $0: stub called with: $*"
|
||||
systemctl reboot
|
||||
STUB
|
||||
|
||||
# steamos-select-branch: no-op stub
|
||||
cat > $out/bin/steamos-select-branch << 'STUB'
|
||||
#!/bin/sh
|
||||
>&2 echo "[JOVIAN] $0: stub called with: $*"
|
||||
exit 0
|
||||
STUB
|
||||
|
||||
# steamos-factory-reset-config: no-op stub
|
||||
cat > $out/bin/steamos-factory-reset-config << 'STUB'
|
||||
#!/bin/sh
|
||||
>&2 echo "[JOVIAN] $0: stub called with: $*"
|
||||
exit 0
|
||||
STUB
|
||||
|
||||
# steamos-firmware-update: no-op stub
|
||||
cat > $out/bin/steamos-firmware-update << 'STUB'
|
||||
#!/bin/sh
|
||||
>&2 echo "[JOVIAN] $0: stub called with: $*"
|
||||
exit 0
|
||||
STUB
|
||||
|
||||
# pkexec: pass through to real pkexec
|
||||
cat > $out/bin/pkexec << 'STUB'
|
||||
#!/bin/sh
|
||||
exec /run/wrappers/bin/pkexec "$@"
|
||||
STUB
|
||||
|
||||
# sudo: strip flags and run the command directly (no escalation).
|
||||
# privileged ops are delegated to root systemd services via systemctl.
|
||||
cat > $out/bin/sudo << 'STUB'
|
||||
#!/bin/sh
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-*) shift ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
exec "$@"
|
||||
STUB
|
||||
|
||||
find $out/bin -type f -exec chmod 755 {} +
|
||||
'';
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
|
||||
jovian = {
|
||||
devices.steamdeck.enable = false;
|
||||
steam = {
|
||||
enable = true;
|
||||
autoStart = true;
|
||||
desktopSession = "niri";
|
||||
user = username;
|
||||
};
|
||||
};
|
||||
|
||||
# Jovian-NixOS requires sddm
|
||||
# https://github.com/Jovian-Experiments/Jovian-NixOS/commit/52f140c07493f8bb6cd0773c7e1afe3e1fd1d1fa
|
||||
services.displayManager.sddm.wayland.enable = true;
|
||||
|
||||
# Disable gamescope from common.nix to avoid conflict with jovian-nixos
|
||||
programs.gamescope.enable = lib.mkForce false;
|
||||
}
|
||||
52
hosts/yarn/disk.nix
Normal file
52
hosts/yarn/disk.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
type = "EF00";
|
||||
size = "500M";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
persistent = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "f2fs";
|
||||
mountpoint = "/persistent";
|
||||
};
|
||||
};
|
||||
nix = {
|
||||
size = "200G";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "f2fs";
|
||||
mountpoint = "/nix";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
nodev = {
|
||||
"/" = {
|
||||
fsType = "tmpfs";
|
||||
mountOptions = [
|
||||
"defaults"
|
||||
"size=2G"
|
||||
"mode=755"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems."/persistent".neededForBoot = true;
|
||||
fileSystems."/nix".neededForBoot = true;
|
||||
}
|
||||
44
hosts/yarn/home.nix
Normal file
44
hosts/yarn/home.nix
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./gui.nix
|
||||
./desktop.nix
|
||||
inputs.json2steamshortcut.homeModules.default
|
||||
];
|
||||
|
||||
home.packages = with pkgs; [
|
||||
protontricks
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/pull/339370#issuecomment-2731336341
|
||||
bs-manager
|
||||
];
|
||||
|
||||
programs.obs-studio = {
|
||||
enable = true;
|
||||
plugins = with pkgs.obs-studio-plugins; [
|
||||
wlrobs
|
||||
obs-backgroundremoval
|
||||
obs-pipewire-audio-capture
|
||||
];
|
||||
};
|
||||
|
||||
services.steam-shortcuts = {
|
||||
enable = true;
|
||||
overwriteExisting = true;
|
||||
steamUserId = lib.strings.toInt (lib.strings.trim (builtins.readFile ./secrets/steam-user-id));
|
||||
shortcuts = [
|
||||
{
|
||||
AppName = "Prism Launcher";
|
||||
Exe = "${pkgs.prismlauncher}/bin/prismlauncher";
|
||||
Icon = "${pkgs.prismlauncher}/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg";
|
||||
Tags = [ "Game" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
38
hosts/yarn/impermanence.nix
Normal file
38
hosts/yarn/impermanence.nix
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
username,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.persistence."/persistent" = {
|
||||
hideMounts = true;
|
||||
directories = [
|
||||
"/var/log"
|
||||
"/var/lib/systemd/coredump"
|
||||
"/var/lib/nixos"
|
||||
"/var/lib/systemd/timers"
|
||||
];
|
||||
|
||||
files = [
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
"/etc/ssh/ssh_host_rsa_key"
|
||||
"/etc/ssh/ssh_host_rsa_key.pub"
|
||||
"/etc/machine-id"
|
||||
];
|
||||
};
|
||||
|
||||
# Bind mount entire home directory from persistent storage
|
||||
# (impermanence doesn't support "." so we do this directly)
|
||||
fileSystems."/home/${username}" = {
|
||||
device = "/persistent/home/${username}";
|
||||
fsType = "none";
|
||||
options = [ "bind" ];
|
||||
neededForBoot = true;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /etc 755 root"
|
||||
];
|
||||
}
|
||||
45
hosts/yarn/vr.nix
Normal file
45
hosts/yarn/vr.nix
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
# for FO4 VR:
|
||||
# doesn't work. it's like the wivrn stuff doesn't transfer past MO2
|
||||
# `echo "PRESSURE_VESSEL_FILESYSTEMS_RW=$XDG_RUNTIME_DIR/wivrn/comp_ipc %command%" | sed -r "s/proton waitforexitandrun .*/proton waitforexitandrun \/media\/games\/fallout4vr_essentials_overhaul\/ModOrganizer.exe \"moshortcut:\/\/:Play Fallout Essentials\" /" | sh`
|
||||
|
||||
services.wivrn = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
|
||||
# Executing it through the systemd service executes WiVRn w/ CAP_SYS_NICE
|
||||
# Resulting in no stutters!
|
||||
autoStart = true;
|
||||
|
||||
# Config for WiVRn
|
||||
config = {
|
||||
enable = true;
|
||||
json = {
|
||||
# 1.0x display scaling
|
||||
scale = 1.0;
|
||||
# 100 Mb/s
|
||||
bitrate = 100000000;
|
||||
encoders = [
|
||||
{
|
||||
encoder = "vaapi";
|
||||
codec = "h265";
|
||||
# 1.0 x 1.0 scaling
|
||||
width = 1.0;
|
||||
height = 1.0;
|
||||
offset_x = 0.0;
|
||||
offset_y = 0.0;
|
||||
}
|
||||
];
|
||||
|
||||
application = [ pkgs.wayvr ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user