# Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). { config, pkgs, ... }: { imports = [ # Include the results of the hardware scan. ./hardware-configuration.nix ]; # Bootloader. boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; boot.supportedFilesystems = [ "nfs" ]; # for disc drive boot.kernelModules = [ "sg" ]; networking.hostName = "kusanagi"; # Define your hostname. # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. # Enable networking networking.networkmanager.enable = true; # for tailscale networking.firewall.trustedInterfaces = [ "tailscale0" ]; networking.firewall.allowedUDPPorts = [ 41641 ]; # Set your time zone. time.timeZone = "America/Chicago"; # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; i18n.extraLocaleSettings = { LC_ADDRESS = "en_US.UTF-8"; LC_IDENTIFICATION = "en_US.UTF-8"; LC_MEASUREMENT = "en_US.UTF-8"; LC_MONETARY = "en_US.UTF-8"; LC_NAME = "en_US.UTF-8"; LC_NUMERIC = "en_US.UTF-8"; LC_PAPER = "en_US.UTF-8"; LC_TELEPHONE = "en_US.UTF-8"; LC_TIME = "en_US.UTF-8"; }; nix.settings.trusted-users = [ "root" "henz" ]; # Enable the X11 windowing system. services.xserver.enable = true; # Enable the GNOME Desktop Environment. services.displayManager.gdm.enable = false; services.desktopManager.gnome.enable = true; services.tailscale.enable = true; services.mpd.enable = false; services.kavita = { enable = true; tokenKeyFile = "/var/lib/kavita/token-key"; settings.Port = 5000; }; systemd.tmpfiles.rules = [ "d /srv/library 2750 henz kavita - -" ]; # For disc drives services.udev.extraRules = '' KERNEL=="sr[0-9]*", GROUP="cdrom", MODE="0660" KERNEL=="sg[0-9]*", GROUP="sg", MODE="0660" ''; # prevent auto-mounting optical disks services.udisks2.enable = true; programs.dconf.enable = true; programs.niri.enable = true; # login screen services.greetd = { enable = true; settings = { default_session = { command = "${pkgs.tuigreet}/bin/tuigreet --time --remember --cmd niri-session"; user = "greeter"; }; }; }; # This is required to let tuigreet write to its cache (for --remember) systemd.services.greetd.serviceConfig = { Type = "idle"; StandardInput = "tty"; StandardOutput = "tty"; StandardError = "journal"; # Better for debugging TTYReset = true; TTYVHangup = true; TTYVTDisallocate = true; }; systemd.user.services.mpd = { description = "Music Player Daemon"; after = [ "network.target" "sound.target" ]; wantedBy = [ "default.target" ]; serviceConfig = { ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon"; Type = "notify"; LimitRTPRIO = 50; LimitRTTIME = "infinity"; }; }; # Configure keymap in X11 services.xserver.xkb = { layout = "us"; variant = ""; }; # Enable CUPS to print documents. services.printing = { enable = true; drivers = with pkgs; [ gutenprint ]; }; services.avahi = { enable = true; nssmdns4 = true; openFirewall = true; }; services.pulseaudio.enable = false; security.rtkit.enable = true; services.pipewire = { enable = true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; jack.enable = true; wireplumber.enable = true; }; # Add this for better pro audio support services.pipewire.extraConfig.pipewire."10-low-latency" = { "context.properties" = { "default.clock.rate" = 48000; "default.clock.quantum" = 256; "default.clock.min-quantum" = 256; "default.clock.max-quantum" = 2048; }; }; # Pin the Scarlett 18i20 to the raw "Pro Audio" profile. # The 26.05 pipewire/wireplumber update began preferring the UCM "HiFi" # profile, which splits the interface into Direct1/Line5/SPDIF1/... sinks and # broke monitoring. This priority rule forces the multichannel Pro Audio # profile statelessly on every boot (and survives future UCM renames). services.pipewire.wireplumber.extraConfig."51-scarlett-pro-audio" = { "device.profile.priority.rules" = [ { matches = [ { "device.name" = "alsa_card.usb-Focusrite_Scarlett_18i20_USB_P9DCR6Y378D1E6-00"; } ]; actions = { update-props = { priorities = [ "pro-audio" ]; }; }; } ]; }; # Real-time audio optimizations security.pam.loginLimits = [ { domain = "@audio"; item = "memlock"; type = "-"; value = "unlimited"; } { domain = "@audio"; item = "rtprio"; type = "-"; value = "99"; } { domain = "@audio"; item = "nofile"; type = "soft"; value = "99999"; } { domain = "@audio"; item = "nofile"; type = "hard"; value = "99999"; } ]; services.nfs.server.enable = false; services.rpcbind.enable = true; services.nfs.idmapd.settings = { General = { Domain = "kusanagi"; # or your actual domain name }; }; # NAS shares. Use the mDNS-resolvable name (bare "milgrim" doesn't resolve) # and automount on first access so a boot-time DNS/network race can't leave # them unmounted (which silently breaks MPD, whose DB points at these paths). fileSystems."/mnt/milgrim-share" = { device = "milgrim.local:/volume1/share"; fsType = "nfs"; options = [ "nfsvers=4" "rsize=8192" "wsize=8192" "_netdev" "noauto" "x-systemd.automount" "x-systemd.idle-timeout=600" "x-systemd.mount-timeout=10s" ]; }; fileSystems."/mnt/milgrim-public" = { device = "milgrim.local:/volume1/public"; fsType = "nfs"; options = [ "nfsvers=4" "rsize=8192" "wsize=8192" "_netdev" "noauto" "x-systemd.automount" "x-systemd.idle-timeout=600" "x-systemd.mount-timeout=10s" ]; }; # Kernel optimizations for audio boot.kernelParams = [ "threadirqs" "preempt=full" # if using a PREEMPT kernel # Add USB audio optimizations "usbcore.usbfs_memory_mb=1024" ]; fonts = { enableDefaultPackages = true; packages = with pkgs; [ noto-fonts-cjk-sans noto-fonts-cjk-serif inter nerd-fonts.symbols-only noto-fonts ibm-plex public-sans adwaita-fonts ]; fontconfig = { enable = true; defaultFonts = { monospace = [ "Berkeley Mono" "Liberation Mono" "Symbols Nerd Font" ]; sansSerif = [ "Liberation Sans" "Noto Sans" ]; serif = [ "Liberation Serif" ]; emoji = [ "Nerd Font Symbols Only" ]; }; # Force ui-sans-serif and system-ui to resolve correctly localConf = '' system-ui Liberation Sans ui-sans-serif Liberation Sans ''; }; fontDir.enable = true; }; # Define a user account. Don't forget to set a password with ‘passwd’. users.users.henz = { isNormalUser = true; description = "Henry Webster"; extraGroups = [ "networkmanager" "wheel" "audio" "cdrom" "optical" "sg" "scanner" "lp" "input" ]; packages = with pkgs; [ blender rocmPackages.rpp rocmPackages.hipcc ardour gnupg pinentry-gnome3 git tmux protonmail-desktop ghostty inkscape darktable nfs-utils imagemagick davinci-resolve-studio alsa-utils alsa-tools usbutils pipewire.jack rocmPackages.rocminfo discord vlc neovim tmux unzip calf gimp xclip gcc pkg-config direnv cargo ripgrep abcde guile autoconf automake libtool gnumake gcc pkg-config mpd mpc ncmpcpp ffmpeg flatpak nushell # for archiving #makemkv libaacs libbdplus libdvdcss psmisc mkvtoolnix dvdbackup chromaprint picard flac bc btop newsboat castero opencode claude-code # hyprland waybar networkmanagerapplet # niri xwayland-satellite fuzzel swaybg stow lua-language-server nil clang-tools marksman gopls ruff basedpyright zls gdb nixfmt gcc nodejs gnumake # scanners simple-scan (pkgs.makeDesktopItem { name = "PICO-8"; desktopName = "PICO-8"; exec = "pico8"; icon = "pico8"; comment = "Fantasy console for making, sharing and playing tiny games"; categories = [ "Game" ]; }) ]; }; nixpkgs.overlays = [ (self: super: { abcde = super.abcde.overrideAttrs (oldAttrs: { # We use postInstall to modify the script after it has been copied to the output directory postInstall = (oldAttrs.postInstall or "") + '' # Patch 1: Allow GetOptions to accept 4 arguments (instead of requiring 5+) sed -i 's/discinfo=i{5,}/discinfo=i{4,}/g' $out/bin/abcde-musicbrainz-tool # Patch 2: Lower the logic check from 5 to 4 sed -i 's/$#discinfo < 5/$#discinfo < 4/g' $out/bin/abcde-musicbrainz-tool ''; }); }) ]; services.pcscd.enable = true; programs.neovim = { enable = true; defaultEditor = true; }; # Allow unfree packages nixpkgs.config.allowUnfree = true; nixpkgs.config.rocmSupport = true; # List packages installed in system profile. To search, run: # $ nix search wget environment.systemPackages = with pkgs; [ # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. # wget neovim ]; environment.sessionVariables = { GSK_RENDERER = "gl"; XCURSOR_THEME = "Bibata-Modern-Classic"; XCURSOR_SIZE = "24"; HYPRCURSOR_THEME = "Bibata-Modern-Classic"; HYPRCURSOR_SIZE = "24"; }; environment.localBinInPath = true; # Graphics setup hardware.graphics = { enable = true; enable32Bit = true; }; hardware.graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ]; # scanner hardware.sane.enable = true; # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions # on your system were taken. It‘s perfectly fine and recommended to leave # this value at the release version of the first install of this system. # Before changing this value read the documentation for this option # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). system.stateVersion = "24.11"; # Did you read the comment? powerManagement.cpuFreqGovernor = "performance"; nix.settings.experimental-features = [ "nix-command" "flakes" ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; }