diff --git a/common.nix b/common.nix index 1856c17..58ee58b 100644 --- a/common.nix +++ b/common.nix @@ -32,23 +32,27 @@ programs.command-not-found.enable = false; # Automatic Garbage Collection - nix.gc.automatic = true; - nix.gc.options = "--delete-older-than 8d"; - nix.settings = { - fallback = true; - # This cache is backed by Misaki's garbage-collected Nix store. Avoid - # retaining narinfo for the default 30 days after its NAR is collected. - narinfo-cache-positive-ttl = 86400; - substituters = [ - "https://tranquil.cachix.org" - "https://cache.ngp.computer" - ]; - trusted-public-keys = [ - "tranquil.cachix.org-1:PoO+mGL6a6LcJiPakMDHN4E218/ei/7v2sxeDtNkSRg=" - "misaki.packetlost.dev:y5Z/utaVBozpL0UAbUQDWLjpm2sVMOoKzyG76n/167A=" - "ngp-upload-1:QX459NA316WkD1gLp3RcRejbX3lNRArLx4JCKwY3FAQ=" - ]; - trusted-users = [ "@wheel" ]; + nix = { + gc = { + automatic = true; + options = "--delete-older-than 8d"; + }; + settings = { + fallback = true; + # This cache is backed by Misaki's garbage-collected Nix store. Avoid + # retaining narinfo for the default 30 days after its NAR is collected. + narinfo-cache-positive-ttl = 86400; + substituters = [ + "https://tranquil.cachix.org" + "https://cache.ngp.computer" + ]; + trusted-public-keys = [ + "tranquil.cachix.org-1:PoO+mGL6a6LcJiPakMDHN4E218/ei/7v2sxeDtNkSRg=" + "misaki.packetlost.dev:y5Z/utaVBozpL0UAbUQDWLjpm2sVMOoKzyG76n/167A=" + "ngp-upload-1:QX459NA316WkD1gLp3RcRejbX3lNRArLx4JCKwY3FAQ=" + ]; + trusted-users = [ "@wheel" ]; + }; }; # protect against the copy fail exploit by blacklisting the affected kernel modules boot.blacklistedKernelModules = [ diff --git a/default-home.nix b/default-home.nix index 2af75b1..ba93c5b 100644 --- a/default-home.nix +++ b/default-home.nix @@ -23,13 +23,14 @@ ./modules/home/package-sets/certificates.nix ./ssh.nix ]; - home.username = "noah"; - home.homeDirectory = "/home/noah"; + home = { + username = "noah"; + homeDirectory = "/home/noah"; + stateVersion = "23.11"; + }; programs.fish = { enable = true; }; - home.stateVersion = "23.11"; - } diff --git a/flake.nix b/flake.nix index 20d0b35..497b9a3 100644 --- a/flake.nix +++ b/flake.nix @@ -84,8 +84,6 @@ home-manager, pre-commit-hooks, agenix, - tangled, - tranquil-pds, valheim-server, nur, ... @@ -138,14 +136,16 @@ nixpkgs.overlays = combinedOverlays; } { - home-manager.useGlobalPkgs = true; - home-manager.useUserPackages = true; - home-manager.users.noah = homeModule; - home-manager.extraSpecialArgs = { - inherit inputs; - } - // nixpkgs.lib.optionalAttrs useUnstable { - inherit unstable; + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users.noah = homeModule; + extraSpecialArgs = { + inherit inputs; + } + // nixpkgs.lib.optionalAttrs useUnstable { + inherit unstable; + }; }; } ] @@ -154,161 +154,165 @@ in { # incomplete - nixosConfigurations.odin = basicSystem { - extraGroups = [ - "libvirtd" - "qemu-libvirtd" - "docker" - "dialout" - ]; - useUnstable = true; - modules = [ - ./host-specific/odin/configuration.nix - valheim-server.nixosModules.default - { - services.centralLogging = { - enable = true; - collector = "client"; - }; - } - ]; - }; - nixosConfigurations.othinus = basicSystem { - extraGroups = [ - "libvirtd" - "qemu-libvirtd" - "docker" - ]; - useUnstable = true; - modules = [ - disko.nixosModules.disko - ./host-specific/othinus/configuration.nix - { - services.centralLogging = { - enable = true; - collector = "client"; - }; - } - ]; - }; - nixosConfigurations.shizuri = basicSystem { - useUnstable = true; - modules = [ - ./host-specific/shizuri/configuration.nix - { - services.centralLogging = { - enable = true; - collector = "client"; - }; - } - ]; - }; - nixosConfigurations.misaki = basicSystem { - useUnstable = true; - extraGroups = [ - "render" - "nats" - "litterbox" - "httpd" - ]; - modules = [ - ./host-specific/misaki/configuration.nix - ]; - # overlays = [ - # (final: prev: { - # ## Override the json object that contains verions and hashes for Immich - # #immich = prev.immich.override { sourcesJSON = ./overrides/immich-sources.json; }; - # ## Fix errors wit numpy version failing to resolve in the immich ML package - # #immich-machine-learning = prev.immich-machine-learning.overrideAttrs - # # (finalAttrs: prevAttrs: { - # # pythonRelaxDeps = prevAttrs.pythonRelaxDeps ++ [ "numpy" ]; - # # }); - # }) - # ]; - }; - nixosConfigurations.edge = basicSystem { - useUnstable = true; - homeModule = ./host-specific/edge/home.nix; - modules = [ - ./host-specific/edge/configuration.nix - { - services.centralLogging = { - enable = true; - collector = "client"; - }; - } - ]; - }; - nixosConfigurations.touma-wsl = basicSystem { - useUnstable = true; - modules = [ - ./host-specific/touma-wsl/configuration.nix - nixos-wsl.nixosModules.default - { - services.centralLogging = { - enable = true; - collector = "client"; - }; - } - ]; - enableNFTables = false; - }; - homeConfigurations."noah-aleister" = home-manager.lib.homeManagerConfiguration { - pkgs = import nixpkgs { - system = "aarch64-darwin"; - overlays = defaultOverlays; - config.allowUnfree = true; + nixosConfigurations = { + odin = basicSystem { + extraGroups = [ + "libvirtd" + "qemu-libvirtd" + "docker" + "dialout" + ]; + useUnstable = true; + modules = [ + ./host-specific/odin/configuration.nix + valheim-server.nixosModules.default + { + services.centralLogging = { + enable = true; + collector = "client"; + }; + } + ]; }; - # Specify your home configuration modules here, for example, - # the path to your home.nix. - modules = [ - ./host-specific/aleister-noah.nix - ./overlays/inetutils.nix - agenix.homeManagerModules.default - ]; - - # Optionally use extraSpecialArgs - # to pass through arguments to home.nix - extraSpecialArgs = { - unstable = import nixpkgs-unstable { - system = "aarch64-darwin"; - overlays = defaultOverlays; - config.allowUnfree = true; - }; - inputs = inputs; + othinus = basicSystem { + extraGroups = [ + "libvirtd" + "qemu-libvirtd" + "docker" + ]; + useUnstable = true; + modules = [ + disko.nixosModules.disko + ./host-specific/othinus/configuration.nix + { + services.centralLogging = { + enable = true; + collector = "client"; + }; + } + ]; + }; + shizuri = basicSystem { + useUnstable = true; + modules = [ + ./host-specific/shizuri/configuration.nix + { + services.centralLogging = { + enable = true; + collector = "client"; + }; + } + ]; + }; + misaki = basicSystem { + useUnstable = true; + extraGroups = [ + "render" + "nats" + "litterbox" + "httpd" + ]; + modules = [ + ./host-specific/misaki/configuration.nix + ]; + # overlays = [ + # (final: prev: { + # ## Override the json object that contains verions and hashes for Immich + # #immich = prev.immich.override { sourcesJSON = ./overrides/immich-sources.json; }; + # ## Fix errors wit numpy version failing to resolve in the immich ML package + # #immich-machine-learning = prev.immich-machine-learning.overrideAttrs + # # (finalAttrs: prevAttrs: { + # # pythonRelaxDeps = prevAttrs.pythonRelaxDeps ++ [ "numpy" ]; + # # }); + # }) + # ]; + }; + edge = basicSystem { + useUnstable = true; + homeModule = ./host-specific/edge/home.nix; + modules = [ + ./host-specific/edge/configuration.nix + { + services.centralLogging = { + enable = true; + collector = "client"; + }; + } + ]; + }; + touma-wsl = basicSystem { + useUnstable = true; + modules = [ + ./host-specific/touma-wsl/configuration.nix + nixos-wsl.nixosModules.default + { + services.centralLogging = { + enable = true; + collector = "client"; + }; + } + ]; + enableNFTables = false; }; }; - homeConfigurations."noah" = - let - system = "x86_64-linux"; + homeConfigurations = { + "noah-aleister" = home-manager.lib.homeManagerConfiguration { pkgs = import nixpkgs { - inherit system; - overlays = defaultOverlays; - config.allowUnfree = true; - }; - unstable = import nixpkgs-unstable { - inherit system; + system = "aarch64-darwin"; overlays = defaultOverlays; config.allowUnfree = true; }; - in - home-manager.lib.homeManagerConfiguration { - inherit pkgs; # Specify your home configuration modules here, for example, # the path to your home.nix. modules = [ - ./default-home.nix - { - nix.package = pkgs.nix; - } + ./host-specific/aleister-noah.nix + ./overlays/inetutils.nix + agenix.homeManagerModules.default ]; + # Optionally use extraSpecialArgs # to pass through arguments to home.nix extraSpecialArgs = { - inherit unstable; - inputs = inputs; + unstable = import nixpkgs-unstable { + system = "aarch64-darwin"; + overlays = defaultOverlays; + config.allowUnfree = true; + }; + inherit inputs; }; }; + "noah" = + let + system = "x86_64-linux"; + pkgs = import nixpkgs { + inherit system; + overlays = defaultOverlays; + config.allowUnfree = true; + }; + unstable = import nixpkgs-unstable { + inherit system; + overlays = defaultOverlays; + config.allowUnfree = true; + }; + in + home-manager.lib.homeManagerConfiguration { + inherit pkgs; + # Specify your home configuration modules here, for example, + # the path to your home.nix. + modules = [ + ./default-home.nix + { + nix.package = pkgs.nix; + } + ]; + # Optionally use extraSpecialArgs + # to pass through arguments to home.nix + extraSpecialArgs = { + inherit unstable; + inherit inputs; + }; + }; + }; packages.x86_64-linux.nix-impatient = let systems = self.nixosConfigurations; @@ -351,6 +355,7 @@ hooks = { check-merge-conflicts.enable = true; check-json.enable = true; + deadnix.enable = true; end-of-file-fixer = { enable = true; excludes = [ "^secrets/" ]; @@ -358,6 +363,7 @@ nixfmt.enable = true; nil.enable = true; luacheck.enable = true; + statix.enable = true; trim-trailing-whitespace = { enable = true; excludes = [ "^secrets/" ]; diff --git a/host-specific/aleister-noah.nix b/host-specific/aleister-noah.nix index e64810d..648f7ae 100644 --- a/host-specific/aleister-noah.nix +++ b/host-specific/aleister-noah.nix @@ -25,8 +25,12 @@ ]; # Home Manager needs a bit of information about you and the paths it should # manage. - home.username = "noah"; - home.homeDirectory = "/Users/noah"; + home = { + username = "noah"; + homeDirectory = "/Users/noah"; + packages = [ pkgs.ncurses ]; + stateVersion = "24.11"; + }; # I generally don't care about unfree stuff nixpkgs.config.allowUnfree = true; @@ -39,8 +43,4 @@ # package = unstable.fish; #}; - home.packages = [ pkgs.ncurses ]; - - home.stateVersion = "24.11"; - } diff --git a/host-specific/edge/configuration.nix b/host-specific/edge/configuration.nix index f5a3419..46e184c 100644 --- a/host-specific/edge/configuration.nix +++ b/host-specific/edge/configuration.nix @@ -63,7 +63,73 @@ }; }; - services.resolved.enable = true; + services = { + resolved.enable = true; + openssh = { + enable = true; + settings = { + KbdInteractiveAuthentication = false; + PasswordAuthentication = false; + PermitRootLogin = "prohibit-password"; + X11Forwarding = false; + }; + }; + tailscale.extraSetFlags = [ "--accept-dns=false" ]; + centralLogging = { + enable = true; + collector = "client"; + }; + haproxy = { + enable = true; + config = '' + global + maxconn 4096 + + defaults + mode tcp + option tcpka + timeout connect 10s + timeout client 2h + timeout server 2h + timeout tunnel 2h + + frontend public_http + bind :::80 v4v6 + mode http + acl spindle_host hdr(host) -i spindle.packetlost.dev + use_backend odin_http if spindle_host + default_backend misaki_http + + backend misaki_http + mode http + server misaki 100.72.241.95:80 check + + backend odin_http + mode http + server odin 100.127.136.117:80 check + + frontend public_https + bind :::443 v4v6 + tcp-request inspect-delay 5s + tcp-request content accept if { req.ssl_hello_type 1 } + use_backend odin_https if { req.ssl_sni -i spindle.packetlost.dev } + default_backend misaki_https + + backend misaki_https + server misaki 100.72.241.95:443 check + + backend odin_https + server odin 100.127.136.117:443 check + + frontend public_plex + bind :::32400 v4v6 + default_backend misaki_plex + + backend misaki_plex + server misaki 100.72.241.95:32400 check + ''; + }; + }; boot = { initrd.availableKernelModules = [ @@ -95,15 +161,6 @@ }; }; - services.openssh = { - enable = true; - settings = { - KbdInteractiveAuthentication = false; - PasswordAuthentication = false; - PermitRootLogin = "prohibit-password"; - X11Forwarding = false; - }; - }; users.users.root = { openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDQFlX3hhXxsqAUYLvF+IX1YWQ+k22OHlqMOjgyNBe9e noah@misaki" @@ -113,68 +170,9 @@ programs.fish.enable = true; - services.tailscale = { - extraSetFlags = [ "--accept-dns=false" ]; - }; - - services.centralLogging = { - enable = true; - collector = "client"; - }; - # Keep TLS termination and certificate renewal on misaki. The edge only # forwards byte streams over Tailscale, which also preserves every existing # nginx virtual host without copying private keys to this machine. - services.haproxy = { - enable = true; - config = '' - global - maxconn 4096 - - defaults - mode tcp - option tcpka - timeout connect 10s - timeout client 2h - timeout server 2h - timeout tunnel 2h - - frontend public_http - bind :::80 v4v6 - mode http - acl spindle_host hdr(host) -i spindle.packetlost.dev - use_backend odin_http if spindle_host - default_backend misaki_http - - backend misaki_http - mode http - server misaki 100.72.241.95:80 check - - backend odin_http - mode http - server odin 100.127.136.117:80 check - - frontend public_https - bind :::443 v4v6 - tcp-request inspect-delay 5s - tcp-request content accept if { req.ssl_hello_type 1 } - use_backend odin_https if { req.ssl_sni -i spindle.packetlost.dev } - default_backend misaki_https - - backend misaki_https - server misaki 100.72.241.95:443 check - - backend odin_https - server odin 100.127.136.117:443 check - - frontend public_plex - bind :::32400 v4v6 - default_backend misaki_plex - - backend misaki_plex - server misaki 100.72.241.95:32400 check - ''; - }; systemd.services.haproxy = { after = [ "tailscaled.service" ]; wants = [ "tailscaled.service" ]; diff --git a/host-specific/misaki/boot.nix b/host-specific/misaki/boot.nix index 40497aa..7acca94 100644 --- a/host-specific/misaki/boot.nix +++ b/host-specific/misaki/boot.nix @@ -1,13 +1,13 @@ -{ ... }: -{ +_: { # Use the systemd-boot EFI boot loader. - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; - - boot.supportedFilesystems = [ "zfs" ]; - boot.zfs.forceImportRoot = false; - boot.zfs.extraPools = [ - "shokuhou" - "mentalout" - ]; + boot = { + loader.systemd-boot.enable = true; + loader.efi.canTouchEfiVariables = true; + supportedFilesystems = [ "zfs" ]; + zfs.forceImportRoot = false; + zfs.extraPools = [ + "shokuhou" + "mentalout" + ]; + }; } diff --git a/host-specific/misaki/hardware-configuration.nix b/host-specific/misaki/hardware-configuration.nix index 159991a..d1d7062 100644 --- a/host-specific/misaki/hardware-configuration.nix +++ b/host-specific/misaki/hardware-configuration.nix @@ -14,43 +14,47 @@ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.kernelPackages = pkgs.linuxPackages; - boot.initrd.availableKernelModules = [ - "nvme" - "xhci_pci" - "ahci" - "usbhid" - "usb_storage" - "sd_mod" - "dm-raid" - "raid1" - ]; - boot.initrd.kernelModules = [ - "dm-snapshot" - "dm-raid" - "raid1" - ]; - boot.kernelModules = [ - "kvm-amd" - "zfs" - ]; - boot.kernelParams = [ "i915.enable_guc=3" ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = { - device = "/dev/disk/by-uuid/1988fa0d-ff4a-44aa-a93e-7f0bf3cea5cf"; - fsType = "ext4"; + boot = { + kernelPackages = pkgs.linuxPackages; + initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "ahci" + "usbhid" + "usb_storage" + "sd_mod" + "dm-raid" + "raid1" + ]; + initrd.kernelModules = [ + "dm-snapshot" + "dm-raid" + "raid1" + ]; + kernelModules = [ + "kvm-amd" + "zfs" + ]; + kernelParams = [ "i915.enable_guc=3" ]; + extraModulePackages = [ ]; }; - fileSystems."/nix" = { - device = "shokuhou/applications/nix"; - fsType = "zfs"; - neededForBoot = true; - }; + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/1988fa0d-ff4a-44aa-a93e-7f0bf3cea5cf"; + fsType = "ext4"; + }; + + "/nix" = { + device = "shokuhou/applications/nix"; + fsType = "zfs"; + neededForBoot = true; + }; - fileSystems."/boot" = { - device = "/dev/disk/by-uuid/81D4-01CD"; - fsType = "vfat"; + "/boot" = { + device = "/dev/disk/by-uuid/81D4-01CD"; + fsType = "vfat"; + }; }; swapDevices = [ ]; diff --git a/host-specific/misaki/networking.nix b/host-specific/misaki/networking.nix index e15ec24..f358121 100644 --- a/host-specific/misaki/networking.nix +++ b/host-specific/misaki/networking.nix @@ -8,130 +8,149 @@ # Pick only one of the below networking options. # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. # networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. - networking.hostName = "misaki"; - # I like systemd-networkd - systemd.network.enable = true; - systemd.network.networks."50-wlp2s0" = { - matchConfig.name = "wlp2s0"; - networkConfig.DHCP = "yes"; - linkConfig.RequiredForOnline = "no"; - }; + networking = { + hostName = "misaki"; + # I like systemd-networkd - networking.tempAddresses = "disabled"; + tempAddresses = "disabled"; - networking.interfaces = { - enp4s0f1 = { - ipv4.addresses = [ - { - address = "192.168.1.3"; - prefixLength = 24; - } - ]; + interfaces = { + enp4s0f1 = { + ipv4.addresses = [ + { + address = "192.168.1.3"; + prefixLength = 24; + } + ]; + }; + }; + defaultGateway = { + address = "192.168.1.1"; + interface = "enp4s0f1"; }; - }; - networking.defaultGateway = { - address = "192.168.1.1"; - interface = "enp4s0f1"; - }; - networking.defaultGateway6 = { - address = "fe80::2870:4eff:fe84:d884"; - interface = "enp4s0f1"; - }; + defaultGateway6 = { + address = "fe80::2870:4eff:fe84:d884"; + interface = "enp4s0f1"; + }; - systemd.network.networks."40-enp4s0f1" = { - dns = [ + nameservers = [ "192.168.1.3" + "45.90.28.93" + "45.90.30.93" ]; - domains = [ - "~." - ]; - }; - - networking.nameservers = [ - "192.168.1.3" - "45.90.28.93" - "45.90.30.93" - ]; - # This is necessary for ZFS - networking.hostId = "5beebabe"; + # This is necessary for ZFS + hostId = "5beebabe"; - networking.useNetworkd = true; - # TODO: static IP @ 192.168.1.2 + useNetworkd = true; + # TODO: static IP @ 192.168.1.2 - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # TODO: allow some ports - networking.firewall = { - enable = true; - allowPing = true; - allowedUDPPorts = [ - # DNS - 53 - # iperf3 - 5201 - ]; - allowedTCPPorts = [ - # DNS over TCP - 53 - # NFSv4 - 2049 - # HTTP(s) - 443 - 80 - # iperf3 - 5201 - 5301 - 5401 - # NATS - 4222 - # Ergochat IRC - 6667 - # Prometheus - 9001 - # Garage RPC - 9003 - # Garage S3 API - 9004 - # Garage Web - 9005 - # Garage K2V API - 9006 - # Garage Admin - 9007 - # AFP via Netatalk - 548 - #9p - 564 - # Misc development - 3000 - # Victoria Logs - 9428 - # Syncthing GUI - 8384 - ]; + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # TODO: allow some ports + firewall = { + enable = true; + allowPing = true; + allowedUDPPorts = [ + # DNS + 53 + # iperf3 + 5201 + ]; + allowedTCPPorts = [ + # DNS over TCP + 53 + # NFSv4 + 2049 + # HTTP(s) + 443 + 80 + # iperf3 + 5201 + 5301 + 5401 + # NATS + 4222 + # Ergochat IRC + 6667 + # Prometheus + 9001 + # Garage RPC + 9003 + # Garage S3 API + 9004 + # Garage Web + 9005 + # Garage K2V API + 9006 + # Garage Admin + 9007 + # AFP via Netatalk + 548 + #9p + 564 + # Misc development + 3000 + # Victoria Logs + 9428 + # Syncthing GUI + 8384 + ]; + }; }; - services.tailscale = { - useRoutingFeatures = "both"; - extraSetFlags = [ - "--accept-dns=false" - ]; + services = { + tailscale = { + useRoutingFeatures = "both"; + extraSetFlags = [ + "--accept-dns=false" + ]; + }; + + networkd-dispatcher = { + enable = true; + rules."50-tailscale-optimizations" = { + onState = [ "routable" ]; + script = '' + ${pkgs.ethtool}/bin/ethtool -K enp4s0f1 rx-udp-gro-forwarding on rx-gro-list off + ''; + }; + }; + + avahi = { + enable = true; + nssmdns4 = true; + nssmdns6 = true; + ipv6 = true; + openFirewall = true; + publish = { + enable = true; + addresses = true; + workstation = true; + userServices = true; + domain = true; + }; + }; }; - services.networkd-dispatcher = { + systemd.network = { enable = true; - rules."50-tailscale-optimizations" = { - onState = [ "routable" ]; - script = '' - ${pkgs.ethtool}/bin/ethtool -K enp4s0f1 rx-udp-gro-forwarding on rx-gro-list off - ''; + networks = { + "50-wlp2s0" = { + matchConfig.name = "wlp2s0"; + networkConfig.DHCP = "yes"; + linkConfig.RequiredForOnline = "no"; + }; + "40-enp4s0f1" = { + dns = [ "192.168.1.3" ]; + domains = [ "~." ]; + }; }; }; @@ -143,19 +162,4 @@ "net.ipv6.conf.enp4s0f1.accept_ra" = lib.mkForce 2; }; - services.avahi = { - enable = true; - nssmdns4 = true; - nssmdns6 = true; - ipv6 = true; - openFirewall = true; - publish = { - enable = true; - addresses = true; - workstation = true; - userServices = true; - domain = true; - }; - }; - } diff --git a/host-specific/misaki/packages.nix b/host-specific/misaki/packages.nix index 348521b..ee1e493 100644 --- a/host-specific/misaki/packages.nix +++ b/host-specific/misaki/packages.nix @@ -1,6 +1,5 @@ { pkgs, - lib, inputs, ... }: diff --git a/host-specific/misaki/services.nix b/host-specific/misaki/services.nix index db4d45e..d35560d 100644 --- a/host-specific/misaki/services.nix +++ b/host-specific/misaki/services.nix @@ -20,1311 +20,1292 @@ in inputs.tranquil-pds.nixosModules.tranquil-pds ]; - services.opencode-v2 = { - hostname = "0.0.0.0"; - port = opencodePort; - openFirewall = true; - }; - - services.zfs = { - autoScrub.enable = true; - }; - services.nfs.server.enable = true; - services.nixery = { - enable = true; - package = nixeryPackages.nixery; - openFirewall = false; - port = 8080; - storage.backend = "filesystem"; - storage.path = "/var/lib/nixery/storage"; - packageSource = { - type = "path"; - path = pkgs.path; - }; - }; - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - programs.gnupg.agent = { - enable = true; - enableSSHSupport = false; - }; - - # Fish shell, the best - programs.fish.enable = true; - - # MOSH, SSH over flakey connections - programs.mosh.enable = true; - - # List services that you want to enable: - - # Enable the OpenSSH daemon. - services.openssh = { - enable = true; - openFirewall = true; - settings.PasswordAuthentication = false; - }; - - # This option is for enabling the bolt daemon for managing Thunderbolt/USB4 Devices. - services.hardware.bolt.enable = true; - - services.ergochat = { - enable = false; - settings = { - accounts = { - authentication-enabled = true; - require-sasl = { - enabled = true; - # Exempt localhost so opers can bootstrap - exempted = [ - "localhost" - "127.0.0.0/8" - "::1/128" - ]; - }; - login-throttling = { - enabled = true; - duration = "1m"; - max-attempts = 3; - }; - multiclient = { - allowed-by-default = true; - always-on = "opt-out"; - auto-away = "opt-out"; - enabled = true; - }; - registration = { - allow-before-connect = false; - bcrypt-cost = 4; - email-verification = { - enabled = false; - }; - # Disabled: only opers can create accounts - enabled = false; - }; + config = { + services = { + opencode-v2 = { + hostname = "0.0.0.0"; + port = opencodePort; + openFirewall = true; + }; + zfs = { + autoScrub.enable = true; }; - channels = { - default-modes = "+ntC"; - registration = { - enabled = true; + nfs.server.enable = true; + nixery = { + enable = true; + package = nixeryPackages.nixery; + openFirewall = false; + port = 8080; + storage.backend = "filesystem"; + storage.path = "/var/lib/nixery/storage"; + packageSource = { + type = "path"; + inherit (pkgs) path; }; }; - datastore = { - autoupgrade = true; - path = "/srv/shokuhou/applications/ergochat/ircd.db"; + # List services that you want to enable: + # Enable the OpenSSH daemon. + openssh = { + enable = true; + openFirewall = true; + settings.PasswordAuthentication = false; }; - history = { - autoreplay-on-join = 0; - autoresize-window = "3d"; - channel-length = 2048; - chathistory-maxmessages = 100; - client-length = 256; - enabled = true; - restrictions = { - expire-time = "1w"; - grace-period = "1h"; - query-cutoff = "none"; + # This option is for enabling the bolt daemon for managing Thunderbolt/USB4 Devices. + hardware.bolt.enable = true; + ergochat = { + enable = false; + settings = { + accounts = { + authentication-enabled = true; + require-sasl = { + enabled = true; + # Exempt localhost so opers can bootstrap + exempted = [ + "localhost" + "127.0.0.0/8" + "::1/128" + ]; + }; + login-throttling = { + enabled = true; + duration = "1m"; + max-attempts = 3; + }; + multiclient = { + allowed-by-default = true; + always-on = "opt-out"; + auto-away = "opt-out"; + enabled = true; + }; + registration = { + allow-before-connect = false; + bcrypt-cost = 4; + email-verification = { + enabled = false; + }; + # Disabled: only opers can create accounts + enabled = false; + }; + }; + channels = { + default-modes = "+ntC"; + registration = { + enabled = true; + }; + }; + datastore = { + autoupgrade = true; + path = "/srv/shokuhou/applications/ergochat/ircd.db"; + }; + history = { + autoreplay-on-join = 0; + autoresize-window = "3d"; + channel-length = 2048; + chathistory-maxmessages = 100; + client-length = 256; + enabled = true; + restrictions = { + expire-time = "1w"; + grace-period = "1h"; + query-cutoff = "none"; + }; + retention = { + allow-individual-delete = true; + enable-account-indexing = true; + }; + tagmsg-storage = { + default = true; + whitelist = [ + "+draft/react" + "+react" + ]; + }; + znc-maxmessages = 2048; + }; + limits = { + awaylen = 390; + channellen = 64; + identlen = 20; + kicklen = 390; + nicklen = 32; + topiclen = 390; + }; + network = { + name = "ngpnet"; + }; + opers = { + admin = { + class = "server-admin"; + whois-line = "is a server admin"; + # Generate with: ergo genpasswd + # Then set this to the bcrypt hash + password = "$2a$04$PLACEHOLDER_GENERATE_WITH_ergo_genpasswd"; + }; + }; + oper-classes = { + chat-moderator = { + title = "Chat Moderator"; + capabilities = [ + "kill" + "ban" + "nofakelag" + "relaymsg" + "vhosts" + "sajoin" + "samode" + "snomasks" + ]; + }; + server-admin = { + title = "Server Admin"; + extends = "chat-moderator"; + capabilities = [ + "rehash" + "accreg" + "chanreg" + "history" + "defcon" + "massmessage" + ]; + }; + }; + server = { + casemapping = "permissive"; + check-ident = true; + enforce-utf = true; + forward-confirm-hostnames = true; + ip-cloaking = { + enabled = false; + }; + ip-limits = { + count = true; + throttle = true; + }; + listeners = { + ":6667" = { }; + }; + lookup-hostnames = true; + max-sendq = "1M"; + name = "ngp.computer"; + relaymsg = { + enabled = true; + }; + }; }; - retention = { - allow-individual-delete = true; - enable-account-indexing = true; + }; + influxdb2 = { + enable = true; + provision = { + enable = false; + initialSetup = { + organization = "ngp"; + bucket = "home-assistant"; + username = "admin"; + retention = 31536000; # 1 year in seconds + passwordFile = config.age.secrets.influxdb-admin-password.path; + tokenFile = config.age.secrets.influxdb-admin-token.path; + }; + users.noah = { + passwordFile = config.age.secrets.influxdb-user-password.path; + }; + organizations.ngp = { + auths = { + admin = { + operator = true; + description = "Admin operator token"; + tokenFile = config.age.secrets.influxdb-admin-token.path; + }; + }; + }; }; - tagmsg-storage = { - default = true; - whitelist = [ - "+draft/react" - "+react" - ]; + }; + # Samba, for shares + # TODO + samba = { + enable = true; + openFirewall = true; + nmbd.enable = true; + winbindd.enable = true; + settings = { + global = { + workgroup = "WORKGROUP"; + "server string" = "misaki"; + security = "user"; + "use sendfile" = "yes"; + "hosts allow" = "192.168.1. 127.0.0.1 localhost"; + "hosts deny" = "0.0.0.0/0"; + "guest account" = "nobody"; + "map to guest" = "bad user"; + deadtime = 30; + }; + shokuhou = { + path = "/srv/shokuhou"; + browseable = "yes"; + "read only" = "no"; + "guest ok" = "no"; + "create mask" = "0644"; + "directory mask" = "0755"; + "force user" = "noah"; + "force group" = "nas"; + }; + mentalout = { + path = "/srv/mentalout"; + browseable = "yes"; + "read only" = "no"; + "guest ok" = "no"; + "create mask" = "0644"; + "directory mask" = "0755"; + "force user" = "noah"; + "force group" = "nas"; + }; }; - znc-maxmessages = 2048; }; - limits = { - awaylen = 390; - channellen = 64; - identlen = 20; - kicklen = 390; - nicklen = 32; - topiclen = 390; + samba-wsdd = { + enable = true; + openFirewall = true; }; - network = { - name = "ngpnet"; + coredns = { + enable = true; + config = '' + packetlost.dev { + hosts ${./coredns/packetlost.dev.hosts} packetlost.dev { + fallthrough + } + # Forward names not defined in the LAN hosts file, including ACME DNS-01. + forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { + tls_servername dd2feb.dns.nextdns.io + health_check 5s + } + bind enp4s0f1 + } + ngp.computer { + hosts ${./coredns/ngp.computer.hosts} ngp.computer { + fallthrough + } + # Forward names not defined in the LAN hosts file, including ACME DNS-01. + forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { + tls_servername dd2feb.dns.nextdns.io + health_check 5s + } + bind enp4s0f1 + } + localhost { + hosts ${./coredns/localhost.hosts} localhost { + fallthrough + } + bind enp4s0f1 + } + # Fix some of plex's services silently failing on IPv6 connections. + # This breaks some features in Plex if it can't build the websocket, + # including, bizarrely, music library refreshing + # This block essentially blacklists AAAA records for the relevant domain + plex.bz { + template IN AAAA plex.bz { + match "^pubsub[0-9]+[.]pop[.][^.]+[.]plex[.]bz[.]?$" + rcode NOERROR + fallthrough + } + # NextDNS + forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { + tls_servername dd2feb.dns.nextdns.io + health_check 5s + } + bind enp4s0f1 + cache + errors + log + } + # Force Steam game delivery through IPv4. SteamPipe content is served from + # steamcontent.com hosts, including cache nodes under that domain. + steamcontent.com { + template IN AAAA steamcontent.com { + match "^(.+[.])?steamcontent[.]com[.]?$" + rcode NOERROR + fallthrough + } + # NextDNS + forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { + tls_servername dd2feb.dns.nextdns.io + health_check 5s + } + bind enp4s0f1 + cache + errors + log + } + . { + # NextDNS + forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { + tls_servername dd2feb.dns.nextdns.io + health_check 5s + } + bind enp4s0f1 + cache + errors + log + } + ''; }; - opers = { - admin = { - class = "server-admin"; - whois-line = "is a server admin"; - # Generate with: ergo genpasswd - # Then set this to the bcrypt hash - password = "$2a$04$PLACEHOLDER_GENERATE_WITH_ergo_genpasswd"; + nats = { + enable = true; + jetstream = true; + user = "nats"; + group = "nats"; + serverName = "misaki"; + dataDir = "/srv/shokuhou/applications/nats"; + validateConfig = false; + settings = { + authorization = { + users = [ + { + user = "seedbox@packetlost.dev"; + permissions = { + publish = [ + "torrents" + "torrents.>" + "$JS.API.INFO" + #"$JS.API.STREAM.INFO.>" + "$KV.torrents.>" + #"$JS.API.STREAM.*.*.OBJ_torrents" + "$JS.API.*.*.OBJ_torrents" + "$JS.API.STREAM.MSG.GET.OBJ_torrents" + "$JS.API.*.*.OBJ_torrents.>" + "$O.torrents.>" + ]; + subscribe = [ + "torrents.>" + "_INBOX.>" + ]; + allow_responses = false; + }; + } + { user = "odin@packetlost.dev"; } + { user = "misaki@packetlost.dev"; } + { user = "noah@packetlost.dev"; } + { user = "touma-nixos@packetlost.dev"; } + ]; + }; + tls = { + cert_file = "/srv/nats/nats.packetlost.dev/cert.pem"; + key_file = "/srv/nats/nats.packetlost.dev/key.pem"; + ca_file = "/srv/nats/minica.pem"; + verify_and_map = true; + }; + jetstream = { + # 50GB + max_file_store = 53687091200; + }; }; }; - oper-classes = { - chat-moderator = { - title = "Chat Moderator"; - capabilities = [ - "kill" - "ban" - "nofakelag" - "relaymsg" - "vhosts" - "sajoin" - "samode" - "snomasks" - ]; - }; - server-admin = { - title = "Server Admin"; - extends = "chat-moderator"; - capabilities = [ - "rehash" - "accreg" - "chanreg" - "history" - "defcon" - "massmessage" + garage = { + enable = false; + package = pkgs.garage_2; + # This is necessary because we use group membership to control access to the + # secrets (the service uses systemd's dynamic user feature). + extraEnvironment.GARAGE_ALLOW_WORLD_READABLE_SECRETS = "true"; + settings = { + data_dir = [ + { + capacity = "1T"; + path = "/srv/shokuhou/applications/garage/data"; + } ]; + metadata_dir = "/srv/shokuhou/applications/garage/meta"; + rpc_bind_addr = "[::]:9003"; + db_engine = "sqlite"; + replication_factor = 1; + rpc_secret_file = config.age.secrets.garage_rpc.path; + s3_api = { + s3_region = "garage"; + api_bind_addr = "[::]:9004"; + root_domain = ".garage.s3.ngp.computer"; + }; + s3_web = { + bind_addr = "[::]:9005"; + root_domain = ".garage.web.ngp.computer"; + index = "index.html"; + }; + k2v_api = { + api_bind_addr = "[::]:9006"; + }; + admin = { + api_bind_addr = "[::]:9007"; + admin_token_file = config.age.secrets.garage_admin.path; + metrics_token_file = config.age.secrets.garage_metrics.path; + }; }; }; - server = { - casemapping = "permissive"; - check-ident = true; - enforce-utf = true; - forward-confirm-hostnames = true; - ip-cloaking = { - enabled = false; - }; - ip-limits = { - count = true; - throttle = true; - }; - listeners = { - ":6667" = { }; - }; - lookup-hostnames = true; - max-sendq = "1M"; - name = "ngp.computer"; - relaymsg = { - enabled = true; + netatalk = { + enable = true; + settings = { + time-machine = { + path = "/srv/shokuhou/backup/timemachine"; + "valid users" = "noah"; + "time machine" = true; + }; }; }; - }; - }; - age.secrets.influxdb-admin-password = { - file = ../../secrets/influxdb-admin-password.age; - owner = "influxdb2"; - group = "influxdb2"; - mode = "600"; - }; - age.secrets.influxdb-admin-token = { - file = ../../secrets/influxdb-admin-token.age; - owner = "influxdb2"; - group = "influxdb2"; - mode = "600"; - }; - age.secrets.influxdb-user-password = { - file = ../../secrets/influxdb-user-password.age; - owner = "influxdb2"; - group = "influxdb2"; - mode = "600"; - }; - services.influxdb2 = { - enable = true; - provision = { - enable = false; - initialSetup = { - organization = "ngp"; - bucket = "home-assistant"; - username = "admin"; - retention = 31536000; # 1 year in seconds - passwordFile = config.age.secrets.influxdb-admin-password.path; - tokenFile = config.age.secrets.influxdb-admin-token.path; - }; - users.noah = { - passwordFile = config.age.secrets.influxdb-user-password.path; + webdav.enable = false; + sftpgo = { + enable = false; + dataDir = /srv/shokuhou/documents/sftpgo; + group = "nas"; }; - organizations.ngp = { - auths = { - admin = { - operator = true; - description = "Admin operator token"; - tokenFile = config.age.secrets.influxdb-admin-token.path; + syncthing = { + enable = true; + openDefaultPorts = true; + group = "nas"; + settings.options.listenAddresses = [ + "[::]" + "0.0.0.0" + ]; + settings = { + folders = { + "Sync" = { + path = "/srv/shokuhou/documents/sync"; + }; }; }; }; - }; - }; - - # Containers and VMs - virtualisation = { - podman = { - enable = true; - dockerCompat = true; - defaultNetwork.settings.dns_enabled = true; - }; - }; - - # Samba, for shares - # TODO - services.samba = { - enable = true; - openFirewall = true; - nmbd.enable = true; - winbindd.enable = true; - settings = { - global = { - workgroup = "WORKGROUP"; - "server string" = "misaki"; - security = "user"; - "use sendfile" = "yes"; - "hosts allow" = "192.168.1. 127.0.0.1 localhost"; - "hosts deny" = "0.0.0.0/0"; - "guest account" = "nobody"; - "map to guest" = "bad user"; - deadtime = 30; - }; - shokuhou = { - path = "/srv/shokuhou"; - browseable = "yes"; - "read only" = "no"; - "guest ok" = "no"; - "create mask" = "0644"; - "directory mask" = "0755"; - "force user" = "noah"; - "force group" = "nas"; - }; - mentalout = { - path = "/srv/mentalout"; - browseable = "yes"; - "read only" = "no"; - "guest ok" = "no"; - "create mask" = "0644"; - "directory mask" = "0755"; - "force user" = "noah"; - "force group" = "nas"; + grafana = { + enable = false; + settings.server = { + http_port = 2342; + domain = "grafana.packetlost.dev"; + http_addr = "127.0.0.1"; + }; }; - }; - }; - services.samba-wsdd = { - enable = true; - openFirewall = true; - }; - - services.coredns = { - enable = true; - config = '' - packetlost.dev { - hosts ${./coredns/packetlost.dev.hosts} packetlost.dev { - fallthrough - } - # Forward names not defined in the LAN hosts file, including ACME DNS-01. - forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { - tls_servername dd2feb.dns.nextdns.io - health_check 5s - } - bind enp4s0f1 - } - ngp.computer { - hosts ${./coredns/ngp.computer.hosts} ngp.computer { - fallthrough - } - # Forward names not defined in the LAN hosts file, including ACME DNS-01. - forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { - tls_servername dd2feb.dns.nextdns.io - health_check 5s - } - bind enp4s0f1 - } - localhost { - hosts ${./coredns/localhost.hosts} localhost { - fallthrough - } - bind enp4s0f1 - } - # Fix some of plex's services silently failing on IPv6 connections. - # This breaks some features in Plex if it can't build the websocket, - # including, bizarrely, music library refreshing - # This block essentially blacklists AAAA records for the relevant domain - plex.bz { - template IN AAAA plex.bz { - match "^pubsub[0-9]+[.]pop[.][^.]+[.]plex[.]bz[.]?$" - rcode NOERROR - fallthrough - } - # NextDNS - forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { - tls_servername dd2feb.dns.nextdns.io - health_check 5s - } - bind enp4s0f1 - cache - errors - log - } - # Force Steam game delivery through IPv4. SteamPipe content is served from - # steamcontent.com hosts, including cache nodes under that domain. - steamcontent.com { - template IN AAAA steamcontent.com { - match "^(.+[.])?steamcontent[.]com[.]?$" - rcode NOERROR - fallthrough - } - # NextDNS - forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { - tls_servername dd2feb.dns.nextdns.io - health_check 5s - } - bind enp4s0f1 - cache - errors - log - } - . { - # NextDNS - forward . tls://2a07:a8c0::dd:2feb:853 tls://2a07:a8c1::dd:2feb:853 tls://45.90.28.93:853 tls://45.90.30.93:853 { - tls_servername dd2feb.dns.nextdns.io - health_check 5s - } - bind enp4s0f1 - cache - errors - log - } - ''; - }; + prometheus = { + enable = false; + port = 9001; + exporters = { + node = { + enable = true; + enabledCollectors = [ "systemd" ]; + port = 9002; + }; + }; - services.nats = { - enable = true; - jetstream = true; - user = "nats"; - group = "nats"; - serverName = "misaki"; - dataDir = "/srv/shokuhou/applications/nats"; - validateConfig = false; - settings = { - authorization = { - users = [ + scrapeConfigs = [ { - user = "seedbox@packetlost.dev"; - permissions = { - publish = [ - "torrents" - "torrents.>" - "$JS.API.INFO" - #"$JS.API.STREAM.INFO.>" - "$KV.torrents.>" - #"$JS.API.STREAM.*.*.OBJ_torrents" - "$JS.API.*.*.OBJ_torrents" - "$JS.API.STREAM.MSG.GET.OBJ_torrents" - "$JS.API.*.*.OBJ_torrents.>" - "$O.torrents.>" - ]; - subscribe = [ - "torrents.>" - "_INBOX.>" - ]; - allow_responses = false; - }; + job_name = "chrysalis"; + static_configs = [ + { targets = [ "127.0.0.1:${builtins.toString config.services.prometheus.exporters.node.port}" ]; } + ]; } - { user = "odin@packetlost.dev"; } - { user = "misaki@packetlost.dev"; } - { user = "noah@packetlost.dev"; } - { user = "touma-nixos@packetlost.dev"; } ]; }; - tls = { - cert_file = "/srv/nats/nats.packetlost.dev/cert.pem"; - key_file = "/srv/nats/nats.packetlost.dev/key.pem"; - ca_file = "/srv/nats/minica.pem"; - verify_and_map = true; + # TODO: figure out how to appropriately configure this + step-ca = { + enable = false; + openFirewall = true; + port = 8443; + address = "0.0.0.0"; + intermediatePasswordFile = /etc/nixos/step-ca-intermediate-ca-password; + settings = builtins.fromJSON (builtins.readFile /home/noah/.step/config/ca.json); }; - jetstream = { - # 50GB - max_file_store = 53687091200; + tangled.knot = { + enable = true; + server = { + hostname = "knot.packetlost.dev"; + owner = "did:plc:hjp23blu4y7bgf7zrzhzdemi"; + secureMode = true; + }; }; - }; - }; - - age.secrets.garage_rpc = { - file = ../../secrets/garage_rpc_secret.age; - owner = "root"; - group = "garage-secrets"; - mode = "640"; - }; - age.secrets.garage_admin = { - file = ../../secrets/garage_admin_secret.age; - owner = "root"; - group = "garage-secrets"; - mode = "640"; - }; - age.secrets.garage_metrics = { - file = ../../secrets/garage_metrics_secret.age; - owner = "root"; - group = "garage-secrets"; - mode = "640"; - }; - systemd.services.garage.serviceConfig.SupplementaryGroups = "garage-secrets"; - services.garage = { - enable = false; - package = pkgs.garage_2; - # This is necessary because we use group membership to control access to the - # secrets (the service uses systemd's dynamic user feature). - extraEnvironment.GARAGE_ALLOW_WORLD_READABLE_SECRETS = "true"; - settings = { - data_dir = [ - { - capacity = "1T"; - path = "/srv/shokuhou/applications/garage/data"; - } - ]; - metadata_dir = "/srv/shokuhou/applications/garage/meta"; - rpc_bind_addr = "[::]:9003"; - db_engine = "sqlite"; - replication_factor = 1; - rpc_secret_file = config.age.secrets.garage_rpc.path; - s3_api = { - s3_region = "garage"; - api_bind_addr = "[::]:9004"; - root_domain = ".garage.s3.ngp.computer"; + tranquil-pds = { + enable = true; + dataDir = "/srv/shokuhou/applications/tranquil"; + database.createLocally = true; + settings = { + server = { + host = "127.0.0.1"; + port = 3030; + hostname = "pds.ngp.computer"; + }; + storage = { + backend = "filesystem"; + path = "/srv/shokuhou/applications/tranquil/blobs"; + }; + tranquil_store.data_dir = "/srv/shokuhou/applications/tranquil/store"; + }; }; - s3_web = { - bind_addr = "[::]:9005"; - root_domain = ".garage.web.ngp.computer"; - index = "index.html"; + pounce = { + enable = true; + package = pkgs.pounce.overrideAttrs (_: rec { + version = "3.2"; + src = pkgs.fetchzip { + url = "https://git.causal.agency/pounce/snapshot/pounce-${version}.tar.gz"; + hash = "sha256-7FAB5kNOg465x8MFTyndJD4pqxJ6Wu3av+CbXGZuxWA="; + }; + }); + dataDir = "/srv/shokuhou/applications/pounce"; + listenAddress = "0.0.0.0"; + openFirewall = true; + tls.acme = { + enable = true; + certificateName = "irc.packetlost.dev"; + domain = "*.irc.packetlost.dev"; + dnsProvider = "porkbun"; + environmentFile = config.age.secrets.acme.path; + }; + networks = { + "libera.irc.packetlost.dev" = { + configFile = config.age.secrets.pounce-libera.path; + settings = { + host = "irc.libera.chat"; + user = "ngp"; + nick = "ngp"; + real = "Noah Pederson"; + join = "#pleroma,#sr.ht,##systemadmins,#lobsters,#python,#hare,#sr.ht.watercooler,#pico.sh,#wilug,#nixos"; + "sasl-external" = true; + "client-cert" = config.age.secrets.pounce-libera-client-cert.path; + "client-priv" = config.age.secrets.pounce-libera-client-key.path; + size = 65536; + "no-names" = true; + }; + }; + "pine64.irc.packetlost.dev" = { + configFile = config.age.secrets.pounce-pine64.path; + settings = { + host = "irc.pine64.org"; + user = "ngp"; + nick = "ngp"; + real = "Noah Pederson"; + join = "#pine64,#pinetime,#pinecil,#nutcracker,#lora,#offtopic"; + "no-names" = true; + }; + }; + "tilde.irc.packetlost.dev" = { + configFile = config.age.secrets.pounce-tilde.path; + settings = { + host = "na.tilde.chat"; + user = "ngp"; + nick = "ngp"; + real = "Noah Pederson"; + join = "#meta,#anime,#anonradio,#bbj,#club,#d&d,#envs,#fp,#hack_the_planet,#linux,#music,#sdf,#tilderadio,#tildetel,#hamradio,#radiofreqs,#pinebox"; + "sasl-external" = true; + "client-cert" = config.age.secrets.pounce-legacy-client-cert.path; + "no-names" = true; + }; + }; + }; }; - k2v_api = { - api_bind_addr = "[::]:9006"; + # A test email server that only works on LAN + maddy = { + enable = true; + openFirewall = true; + primaryDomain = "misaki.local"; + ensureAccounts = [ + "noah@misaki.local" + "postmaster@misaki.local" + "test@misaki.local" + ]; + ensureCredentials = { + "noah@misaki.local".passwordFile = "${pkgs.writeText "noah" "Password123"}"; + "postmaster@misaki.local".passwordFile = "${pkgs.writeText "noah" "Password123"}"; + "test@misaki.local".passwordFile = "${pkgs.writeText "test" "Password123"}"; + }; }; - admin = { - api_bind_addr = "[::]:9007"; - admin_token_file = config.age.secrets.garage_admin.path; - metrics_token_file = config.age.secrets.garage_metrics.path; + nix-serve = { + enable = true; + package = unstable.nix-serve-ng; + secretKeyFile = config.age.secrets.nix-serve.path; + openFirewall = false; + extraParams = "+RTS -N4 -RTS"; }; - }; - }; - - services.netatalk = { - enable = true; - settings = { - time-machine = { - path = "/srv/shokuhou/backup/timemachine"; - "valid users" = "noah"; - "time machine" = true; + ncps = { + enable = true; + analytics.reporting.enable = false; + server.addr = "127.0.0.1:8501"; + cache = { + hostName = "cache.ngp.computer"; + allowPutVerb = true; + secretKeyPath = config.age.secrets.nix-serve.path; + upstream = { + urls = [ "http://127.0.0.1:${toString config.services.nix-serve.port}" ]; + publicKeys = [ "misaki.packetlost.dev:y5Z/utaVBozpL0UAbUQDWLjpm2sVMOoKzyG76n/167A=" ]; + }; + }; }; - }; - }; - - services.webdav.enable = false; - services.sftpgo = { - enable = false; - dataDir = /srv/shokuhou/documents/sftpgo; - group = "nas"; - }; - services.syncthing = { - enable = true; - openDefaultPorts = true; - group = "nas"; - settings.options.listenAddresses = [ - "[::]" - "0.0.0.0" - ]; - settings = { - folders = { - "Sync" = { - path = "/srv/shokuhou/documents/sync"; + plex = { + enable = true; + openFirewall = false; # we proxy this with nginx + group = "nas"; + user = "noah"; + package = unstable.plex.override { + plexRaw = unstable.plexRaw.overrideAttrs rec { + version = "1.43.4.10903-e5521bd8c"; + src = unstable.fetchurl { + url = "https://downloads.plex.tv/plex-media-server-new/${version}/debian/plexmediaserver_${version}_amd64.deb"; + sha256 = "sha256-b2ocgzbXeeHyAVGmk0NJiEutb2pmsYorGJuW5Vw7Pts="; + }; + }; }; }; - }; - }; - - services.grafana = { - enable = false; - settings.server.http_port = 2342; - settings.server.domain = "grafana.packetlost.dev"; - settings.server.http_addr = "127.0.0.1"; - }; - - services.prometheus = { - enable = false; - port = 9001; - exporters = { - node = { + jellyfin = { enable = true; - enabledCollectors = [ "systemd" ]; - port = 9002; + openFirewall = true; + user = "noah"; + group = "nas"; + logDir = "/srv/shokuhou/applications/jellyfin/log"; + cacheDir = "/srv/shokuhou/applications/jellyfin/cache"; + dataDir = "/srv/shokuhou/applications/jellyfin/data"; + configDir = "/srv/shokuhou/applications/jellyfin/config"; }; - }; - - scrapeConfigs = [ - { - job_name = "chrysalis"; - static_configs = [ - { targets = [ "127.0.0.1:${builtins.toString config.services.prometheus.exporters.node.port}" ]; } - ]; - } - ]; - }; - - # TODO: figure out how to appropriately configure this - services.step-ca = { - enable = false; - openFirewall = true; - port = 8443; - address = "0.0.0.0"; - intermediatePasswordFile = /etc/nixos/step-ca-intermediate-ca-password; - settings = builtins.fromJSON (builtins.readFile /home/noah/.step/config/ca.json); - }; - - services.tangled.knot = { - enable = true; - server = { - hostname = "knot.packetlost.dev"; - owner = "did:plc:hjp23blu4y7bgf7zrzhzdemi"; - secureMode = true; - }; - }; - - services.tranquil-pds = { - enable = true; - dataDir = "/srv/shokuhou/applications/tranquil"; - database.createLocally = true; - settings = { - server = { - host = "127.0.0.1"; - port = 3030; - hostname = "pds.ngp.computer"; + foundryvtt = { + enable = false; + package = inputs.foundryvtt.packages.${pkgs.stdenv.hostPlatform.system}.foundryvtt_13; + dataDir = "/srv/shokuhou/applications/foundry"; + hostName = "foundry.ngp.computer"; + minifyStaticFiles = true; + proxyPort = 443; + proxySSL = true; + upnp = false; }; - storage = { - backend = "filesystem"; - path = "/srv/shokuhou/applications/tranquil/blobs"; + victorialogs = { + enable = true; + basicAuthUsername = "noah"; + basicAuthPasswordFile = config.age.secrets.victoriapass.path; }; - tranquil_store.data_dir = "/srv/shokuhou/applications/tranquil/store"; - }; - }; - age.secrets.tranquil-pds-env = { - file = ../../secrets/tranquil-pds-env.age; - owner = "tranquil-pds"; - group = "tranquil-pds"; - }; - systemd.services.tranquil-pds.serviceConfig = { - EnvironmentFile = config.age.secrets.tranquil-pds-env.path; - ReadWritePaths = [ - "/srv/shokuhou/applications/tranquil" - ]; - }; - - age.secrets.acme = { - file = ../../secrets/porkbun-api-key.age; - owner = "root"; - group = "acme"; - }; - - security.acme = { - acceptTerms = true; - defaults.email = "noah@packetlost.dev"; - certs = - pkgs.lib.genAttrs - [ - "plex.packetlost.dev" - "img.ngp.computer" - "books.ngp.computer" - "kosync.ngp.computer" - "knot.packetlost.dev" - "files.ngp.computer" - "foundry.ngp.computer" - "cache.ngp.computer" - "code.ngp.computer" - "photos.ngp.computer" - "jellyfin.packetlost.dev" - "id.ngp.computer" - "stats.ngp.computer" - "nixery.ngp.computer" - "pds.ngp.computer" - ] - (name: { - group = "httpd"; - dnsProvider = "porkbun"; - environmentFile = config.age.secrets.acme.path; - # Direct authoritative queries select IPv6, which the ISP drops. - extraLegoFlags = - if name == "books.ngp.computer" then - [ "--dns.propagation-disable-ans" ] - else if name == "kosync.ngp.computer" then - [ - "--dns.resolvers" - "1.1.1.1:53" - "--dns.propagation-disable-ans" - ] - else - [ ]; - }); - }; - - age.secrets.pounce-libera = { - file = ../../secrets/pounce-libera.age; - owner = "pounce"; - group = "pounce"; - mode = "600"; - }; - age.secrets.pounce-pine64 = { - file = ../../secrets/pounce-pine64.age; - owner = "pounce"; - group = "pounce"; - mode = "600"; - }; - age.secrets.pounce-tilde = { - file = ../../secrets/pounce-tilde.age; - owner = "pounce"; - group = "pounce"; - mode = "600"; - }; - age.secrets.pounce-libera-client-cert = { - file = ../../secrets/pounce-libera-client-cert.age; - owner = "pounce"; - group = "pounce"; - mode = "600"; - }; - age.secrets.pounce-libera-client-key = { - file = ../../secrets/pounce-libera-client-key.age; - owner = "pounce"; - group = "pounce"; - mode = "600"; - }; - age.secrets.pounce-legacy-client-cert = { - file = ../../secrets/pounce-legacy-client-cert.age; - owner = "pounce"; - group = "pounce"; - mode = "600"; - }; - - services.pounce = { - enable = true; - package = pkgs.pounce.overrideAttrs (old: rec { - version = "3.2"; - src = pkgs.fetchzip { - url = "https://git.causal.agency/pounce/snapshot/pounce-${version}.tar.gz"; - hash = "sha256-7FAB5kNOg465x8MFTyndJD4pqxJ6Wu3av+CbXGZuxWA="; + # Accept syslog from the other hosts (see modules/log-shipping.nix). + centralLogging = { + enable = true; + collector = "server"; }; - }); - dataDir = "/srv/shokuhou/applications/pounce"; - listenAddress = "0.0.0.0"; - openFirewall = true; - tls.acme = { - enable = true; - certificateName = "irc.packetlost.dev"; - domain = "*.irc.packetlost.dev"; - dnsProvider = "porkbun"; - environmentFile = config.age.secrets.acme.path; - }; - networks = { - "libera.irc.packetlost.dev" = { - configFile = config.age.secrets.pounce-libera.path; - settings = { - host = "irc.libera.chat"; - user = "ngp"; - nick = "ngp"; - real = "Noah Pederson"; - join = "#pleroma,#sr.ht,##systemadmins,#lobsters,#python,#hare,#sr.ht.watercooler,#pico.sh,#wilug,#nixos"; - "sasl-external" = true; - "client-cert" = config.age.secrets.pounce-libera-client-cert.path; - "client-priv" = config.age.secrets.pounce-libera-client-key.path; - size = 65536; - "no-names" = true; + victoriatraces = { + enable = true; + listenAddress = "127.0.0.1:10428"; + }; + teamspeak3 = { + enable = true; + openFirewall = true; + openFirewallServerQuery = true; + }; + immich = { + enable = true; + package = unstable.immich; + accelerationDevices = [ "/dev/dri/renderD128" ]; + mediaLocation = "/srv/shokuhou/pictures/immich"; + redis = { + enable = false; + host = "127.0.0.1"; + port = 6379; }; }; - "pine64.irc.packetlost.dev" = { - configFile = config.age.secrets.pounce-pine64.path; + redis.servers.shared = { + enable = true; + port = 6379; + appendOnly = true; + settings.bind = "127.0.0.1"; + }; + dir2opds = { + enable = true; + user = "noah"; + group = "nas"; + libraryDir = "/srv/shokuhou/books"; + koreaderMixedFeeds = false; + port = 8081; + openFirewall = false; + }; + koreader-sync-server = { + enable = true; + enableUserRegistration = false; + redisPort = 6379; + }; + # The package is broken for some reason + navidrome = { + enable = false; + openFirewall = true; settings = { - host = "irc.pine64.org"; - user = "ngp"; - nick = "ngp"; - real = "Noah Pederson"; - join = "#pine64,#pinetime,#pinecil,#nutcracker,#lora,#offtopic"; - "no-names" = true; + MusicFolder = "/srv/shokuhou/music"; }; }; - "tilde.irc.packetlost.dev" = { - configFile = config.age.secrets.pounce-tilde.path; + pocket-id = { + enable = true; + package = unstable.pocket-id; settings = { - host = "na.tilde.chat"; - user = "ngp"; - nick = "ngp"; - real = "Noah Pederson"; - join = "#meta,#anime,#anonradio,#bbj,#club,#d&d,#envs,#fp,#hack_the_planet,#linux,#music,#sdf,#tilderadio,#tildetel,#hamradio,#radiofreqs,#pinebox"; - "sasl-external" = true; - "client-cert" = config.age.secrets.pounce-legacy-client-cert.path; - "no-names" = true; + TRUST_PROXY = true; + APP_URL = "https://id.ngp.computer"; + ENCRYPTION_KEY_FILE = "${config.age.secrets.pocket-id-encryption-key.path}"; }; + dataDir = "/srv/shokuhou/applications/pocket-id"; }; - }; - }; - - # A test email server that only works on LAN - services.maddy = { - enable = true; - openFirewall = true; - primaryDomain = "misaki.local"; - ensureAccounts = [ - "noah@misaki.local" - "postmaster@misaki.local" - "test@misaki.local" - ]; - ensureCredentials = { - "noah@misaki.local".passwordFile = "${pkgs.writeText "noah" "Password123"}"; - "postmaster@misaki.local".passwordFile = "${pkgs.writeText "noah" "Password123"}"; - "test@misaki.local".passwordFile = "${pkgs.writeText "test" "Password123"}"; - }; - }; - - age.secrets.nix-serve = { - file = ../../secrets/nix-serve-secret-key.age; - owner = "root"; - group = "root"; - }; - age.secrets.nix-cache-push = { - file = ../../secrets/nix-cache-push.age; - owner = "noah"; - group = "nas"; - }; - services.nix-serve = { - enable = true; - package = unstable.nix-serve-ng; - secretKeyFile = config.age.secrets.nix-serve.path; - openFirewall = false; - extraParams = "+RTS -N4 -RTS"; - }; - services.ncps = { - enable = true; - analytics.reporting.enable = false; - server.addr = "127.0.0.1:8501"; - cache = { - hostName = "cache.ngp.computer"; - allowPutVerb = true; - secretKeyPath = config.age.secrets.nix-serve.path; - upstream = { - urls = [ "http://127.0.0.1:${toString config.services.nix-serve.port}" ]; - publicKeys = [ "misaki.packetlost.dev:y5Z/utaVBozpL0UAbUQDWLjpm2sVMOoKzyG76n/167A=" ]; - }; - }; - }; + # Nginx Reverse SSL Proxy + nginx = { + enable = true; + group = "nas"; + user = "noah"; + appendConfig = '' + worker_processes auto; + ''; + eventsConfig = '' + worker_connections 4096; + ''; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; - services.plex = { - enable = true; - openFirewall = false; # we proxy this with nginx - group = "nas"; - user = "noah"; - package = unstable.plex.override { - plexRaw = unstable.plexRaw.overrideAttrs rec { - version = "1.43.4.10903-e5521bd8c"; - src = unstable.fetchurl { - url = "https://downloads.plex.tv/plex-media-server-new/${version}/debian/plexmediaserver_${version}_amd64.deb"; - sha256 = "sha256-b2ocgzbXeeHyAVGmk0NJiEutb2pmsYorGJuW5Vw7Pts="; + upstreams.nixery.servers = { + "127.0.0.1:${toString config.services.nixery.port}" = { }; + "192.168.1.6:80" = { }; }; - }; - }; - }; - - services.jellyfin = { - enable = true; - openFirewall = true; - user = "noah"; - group = "nas"; - logDir = "/srv/shokuhou/applications/jellyfin/log"; - cacheDir = "/srv/shokuhou/applications/jellyfin/cache"; - dataDir = "/srv/shokuhou/applications/jellyfin/data"; - configDir = "/srv/shokuhou/applications/jellyfin/config"; - }; - - services.foundryvtt = { - enable = false; - package = inputs.foundryvtt.packages.${pkgs.stdenv.hostPlatform.system}.foundryvtt_13; - dataDir = "/srv/shokuhou/applications/foundry"; - hostName = "foundry.ngp.computer"; - minifyStaticFiles = true; - proxyPort = 443; - proxySSL = true; - upnp = false; - }; - - age.secrets.victoriapass = { - file = ../../secrets/victoria-secret.age; - owner = "root"; - group = "root"; - }; - age.secrets.victoriatraces-write-pass = { - file = ../../secrets/victoriatraces-write-pass.age; - owner = "root"; - group = "root"; - }; - services.victorialogs = { - enable = true; - basicAuthUsername = "noah"; - basicAuthPasswordFile = config.age.secrets.victoriapass.path; - }; - # Accept syslog from the other hosts (see modules/log-shipping.nix). - services.centralLogging = { - enable = true; - collector = "server"; - }; - - services.victoriatraces = { - enable = true; - listenAddress = "127.0.0.1:10428"; - }; + virtualHosts = { + "code.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + extraConfig = '' + allow 192.168.1.0/24; + allow 100.64.0.0/10; + deny all; + ''; + locations."/" = { + proxyPass = "http://192.168.1.6:${toString opencodePort}"; + proxyWebsockets = true; + extraConfig = '' + proxy_buffering off; + proxy_read_timeout 3600s; + ''; + }; + }; + "photos.ngp.computer" = { + enableACME = true; + acmeRoot = null; + forceSSL = true; + locations."/" = { + proxyPass = "http://[::1]:${toString config.services.immich.port}"; + proxyWebsockets = true; + recommendedProxySettings = true; + extraConfig = '' + client_max_body_size 50000M; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + ''; + }; + }; + "books.ngp.computer" = { + enableACME = true; + acmeRoot = null; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.dir2opds.port}"; + basicAuthFile = config.age.secrets.opds-password.path; + }; + }; + "kosync.ngp.computer" = { + enableACME = true; + acmeRoot = null; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.koreader-sync-server.port}"; + }; + }; + "foundry.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.foundryvtt.port}"; + proxyWebsockets = true; + }; + }; + "img.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + root = "/srv/shokuhou/pictures/public"; + extraConfig = '' + sendfile on; + autoindex_exact_size on; + tcp_nopush on; + ''; + locations."/" = { + extraConfig = '' + autoindex on; + autoindex_exact_size on; + alias /srv/shokuhou/pictures/public/$1; + ''; + }; + }; + "files.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + root = null; + extraConfig = '' + sendfile on; + tcp_nopush on; + ''; + locations."/books/" = { + extraConfig = '' + autoindex on; + autoindex_exact_size on; + alias /srv/shokuhou/books/sync/$1; + ''; + }; + locations."/music/" = { + extraConfig = '' + autoindex on; + autoindex_exact_size on; + alias /srv/shokuhou/music/public/$1; + ''; + }; + }; + "jellyfin.packetlost.dev" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + http2 = true; + locations."/" = { + proxyPass = "http://localhost:8096/"; + }; + }; + "cache.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + http2 = true; + extraConfig = '' + ssl_session_cache shared:CacheSSL:50m; + ''; + locations."/" = { + proxyPass = "http://${config.services.ncps.server.addr}"; + extraConfig = '' + limit_except GET { deny all; } + proxy_buffering off; + gzip_comp_level 1; + access_log off; + ''; + }; + locations."/upload/" = { + proxyPass = "http://${config.services.ncps.server.addr}"; + basicAuthFile = config.age.secrets.nix-cache-push.path; + extraConfig = '' + client_max_body_size 0; + proxy_request_buffering off; + proxy_http_version 1.1; + proxy_read_timeout 3600s; + ''; + }; + }; + "nixery.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + http2 = true; + locations."/".proxyPass = "http://nixery"; + }; + "knot.packetlost.dev" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + http2 = true; + locations."/" = { + proxyPass = "http://${config.services.tangled.knot.server.listenAddr}"; + proxyWebsockets = true; + }; + locations."/events" = { + proxyPass = "http://${config.services.tangled.knot.server.listenAddr}"; + extraConfig = '' + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + ''; + }; + }; + "id.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + http2 = true; + locations."/".proxyPass = "http://localhost:1411/"; + }; + "pds.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + http2 = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.tranquil-pds.settings.server.port}"; + proxyWebsockets = true; + extraConfig = '' + client_max_body_size 50000M; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + ''; + }; + }; + "stats.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + http2 = true; + locations."/".proxyPass = "http://localhost:8086/"; + }; + "traces.ngp.computer" = { + http2 = true; + extraConfig = '' + allow 192.168.0.0/16; + allow 10.0.0.0/8; + allow 172.16.0.0/12; + allow 127.0.0.1; + allow ::1; + deny all; + ''; + locations."/" = { + proxyPass = "http://localhost:10428/"; + basicAuthFile = "/var/lib/nginx/victoriatraces.htpasswd"; + }; + locations."/insert/" = { + proxyPass = "http://localhost:10428/"; + basicAuthFile = "/var/lib/nginx/victoriatraces-insert.htpasswd"; + }; + }; - system.activationScripts.nginx-victoriatraces-htpasswd = '' - mkdir -p /var/lib/nginx - ${pkgs.apacheHttpd}/bin/htpasswd -nbB noah "$(cat ${config.age.secrets.victoriapass.path})" > /var/lib/nginx/victoriatraces.htpasswd - ${pkgs.apacheHttpd}/bin/htpasswd -nbB noah "$(cat ${config.age.secrets.victoriapass.path})" > /var/lib/nginx/victoriatraces-insert.htpasswd - ${pkgs.apacheHttpd}/bin/htpasswd -nbB publisher "$(cat ${config.age.secrets.victoriatraces-write-pass.path})" >> /var/lib/nginx/victoriatraces-insert.htpasswd - ''; + # give a name to the virtual host. It also becomes the server name. + "plex.packetlost.dev" = { + # Since we want a secure connection, we force SSL + forceSSL = true; + enableACME = true; + acmeRoot = null; - # Litterbox, collect my IRC logs - systemd = { - services = { - "litterbox@" = { - path = [ pkgs.litterbox ]; - serviceConfig = { - StartLimitIntervalSec = 5; - StartLimitBurst = 10; - Restart = "on-failure"; - RestartSec = "10s"; - Type = "simple"; - ExecStart = "${pkgs.litterbox}/bin/litterbox /srv/litterbox/%i.conf"; - ExecReload = "kill -USR1 $MAINPID"; - User = "noah"; - Group = "litterbox"; - }; - }; + # http2 can more performant for streaming: https://blog.cloudflare.com/introducing-http2/ + http2 = true; - #"litterbox@libera.irc.packetlost.dev" = { - # overrideStrategy = "asDropin"; - # wantedBy = [ "multi-user.target" ]; - #}; - "update-downstream-src" = { - path = with pkgs; [ - rc - coreutils - git - openssh - ]; - script = "exec ${./scripts/update-src}"; - serviceConfig = { - Type = "oneshot"; - User = "noah"; - WorkingDirectory = "/srv/src"; - }; - }; - }; - timers = { - "update-downstream-src" = { - wantedBy = [ "timers.target" ]; - timerConfig = { - OnCalendar = "daily"; - Persistent = true; - }; - }; - }; - }; + # Provide the ssl cert and key for the vhost + # These are filled in automatically with ACME + extraConfig = '' - services.teamspeak3 = { - enable = true; - openFirewall = true; - openFirewallServerQuery = true; - }; + #Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause + send_timeout 100m; - services.immich = { - enable = true; - package = unstable.immich; - accelerationDevices = [ "/dev/dri/renderD128" ]; - mediaLocation = "/srv/shokuhou/pictures/immich"; - redis = { - enable = false; - host = "127.0.0.1"; - port = 6379; - }; - }; - services.redis.servers.shared = { - enable = true; - port = 6379; - appendOnly = true; - settings.bind = "127.0.0.1"; - }; - users.users.immich.extraGroups = [ - "video" - "render" - "nas" - ]; + # Why this is important: https://blog.cloudflare.com/ocsp-stapling-how-cloudflare-just-made-ssl-30/ + ssl_stapling on; + ssl_stapling_verify on; - services.dir2opds = { - enable = true; - user = "noah"; - group = "nas"; - libraryDir = "/srv/shokuhou/books"; - koreaderMixedFeeds = false; - port = 8081; - openFirewall = false; - }; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_prefer_server_ciphers on; + #Intentionally not hardened for security for player support and encryption video streams has a lot of overhead with something like AES-256-GCM-SHA384. + ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; - services.koreader-sync-server = { - enable = true; - enableUserRegistration = false; - redisPort = 6379; - }; - systemd.services.koreader-sync-server = { - after = [ "redis-shared.service" ]; - requires = [ "redis-shared.service" ]; - }; + # Forward real ip and host to Plex + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $server_addr; + proxy_set_header Referer $server_addr; + proxy_set_header Origin $server_addr; - age.secrets.opds-password = { - file = ../../secrets/opds-password.age; - owner = "noah"; - group = "nas"; - mode = "440"; - }; + # Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. + gzip on; + gzip_vary on; + gzip_min_length 1000; + gzip_proxied any; + gzip_types text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml; + gzip_disable "MSIE [1-6]\."; - # The package is broken for some reason - services.navidrome = { - enable = false; - openFirewall = true; - settings = { - MusicFolder = "/srv/shokuhou/music"; - }; - }; - systemd.services.navidrome.serviceConfig = { - BindReadOnlyPaths = [ - "/srv/shokuhou/music" - ]; - }; + # Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones. + # Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more + client_max_body_size 100M; - age.secrets.pocket-id-encryption-key = { - file = ../../secrets/pocket-id-encryption-key.age; - owner = "pocket-id"; - group = "pocket-id"; - mode = "600"; - }; - services.pocket-id = { - enable = true; - package = unstable.pocket-id; - settings = { - TRUST_PROXY = true; - APP_URL = "https://id.ngp.computer"; - ENCRYPTION_KEY_FILE = "${config.age.secrets.pocket-id-encryption-key.path}"; - }; - dataDir = "/srv/shokuhou/applications/pocket-id"; - }; - users.users.pocket-id.extraGroups = [ "nas" ]; + # Plex headers + proxy_set_header X-Plex-Client-Identifier $http_x_plex_client_identifier; + proxy_set_header X-Plex-Device $http_x_plex_device; + proxy_set_header X-Plex-Device-Name $http_x_plex_device_name; + proxy_set_header X-Plex-Platform $http_x_plex_platform; + proxy_set_header X-Plex-Platform-Version $http_x_plex_platform_version; + proxy_set_header X-Plex-Product $http_x_plex_product; + proxy_set_header X-Plex-Token $http_x_plex_token; + proxy_set_header X-Plex-Version $http_x_plex_version; + proxy_set_header X-Plex-Nocache $http_x_plex_nocache; + proxy_set_header X-Plex-Provides $http_x_plex_provides; + proxy_set_header X-Plex-Device-Vendor $http_x_plex_device_vendor; + proxy_set_header X-Plex-Model $http_x_plex_model; - # Nginx Reverse SSL Proxy - services.nginx = { - enable = true; - group = "nas"; - user = "noah"; - appendConfig = '' - worker_processes auto; - ''; - eventsConfig = '' - worker_connections 4096; - ''; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; + # Websockets + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; - upstreams.nixery.servers = { - "127.0.0.1:${toString config.services.nixery.port}" = { }; - "192.168.1.6:80" = { }; - }; + # Buffering off send to the client as soon as the data is received from Plex. + proxy_redirect off; + proxy_buffering off; + ''; - virtualHosts."code.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - extraConfig = '' - allow 192.168.1.0/24; - allow 100.64.0.0/10; - deny all; - ''; - locations."/" = { - proxyPass = "http://192.168.1.6:${toString opencodePort}"; - proxyWebsockets = true; - extraConfig = '' - proxy_buffering off; - proxy_read_timeout 3600s; - ''; - }; - }; - virtualHosts."photos.ngp.computer" = { - enableACME = true; - acmeRoot = null; - forceSSL = true; - locations."/" = { - proxyPass = "http://[::1]:${toString config.services.immich.port}"; - proxyWebsockets = true; - recommendedProxySettings = true; - extraConfig = '' - client_max_body_size 50000M; - proxy_read_timeout 600s; - proxy_send_timeout 600s; - send_timeout 600s; - ''; - }; - }; - virtualHosts."books.ngp.computer" = { - enableACME = true; - acmeRoot = null; - forceSSL = true; - locations."/" = { - proxyPass = "http://127.0.0.1:${toString config.services.dir2opds.port}"; - basicAuthFile = config.age.secrets.opds-password.path; - }; - }; - virtualHosts."kosync.ngp.computer" = { - enableACME = true; - acmeRoot = null; - forceSSL = true; - locations."/" = { - proxyPass = "http://127.0.0.1:${toString config.services.koreader-sync-server.port}"; - }; - }; - virtualHosts."foundry.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - locations."/" = { - proxyPass = "http://127.0.0.1:${toString config.services.foundryvtt.port}"; - proxyWebsockets = true; - }; - }; - virtualHosts."img.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - root = "/srv/shokuhou/pictures/public"; - extraConfig = '' - sendfile on; - autoindex_exact_size on; - tcp_nopush on; - ''; - locations."/" = { - extraConfig = '' - autoindex on; - autoindex_exact_size on; - alias /srv/shokuhou/pictures/public/$1; - ''; - }; - }; - virtualHosts."files.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - root = null; - extraConfig = '' - sendfile on; - tcp_nopush on; - ''; - locations."/books/" = { - extraConfig = '' - autoindex on; - autoindex_exact_size on; - alias /srv/shokuhou/books/sync/$1; - ''; - }; - locations."/music/" = { - extraConfig = '' - autoindex on; - autoindex_exact_size on; - alias /srv/shokuhou/music/public/$1; - ''; + locations."/" = { + recommendedProxySettings = false; + proxyPass = "http://localhost:32400/"; + }; + }; + }; }; }; - virtualHosts."jellyfin.packetlost.dev" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - http2 = true; - locations."/" = { - proxyPass = "http://localhost:8096/"; + + programs = { + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + gnupg.agent = { + enable = true; + enableSSHSupport = false; }; + # Fish shell, the best + fish.enable = true; + # MOSH, SSH over flakey connections + mosh.enable = true; }; - virtualHosts."cache.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - http2 = true; - extraConfig = '' - ssl_session_cache shared:CacheSSL:50m; - ''; - locations."/" = { - proxyPass = "http://${config.services.ncps.server.addr}"; - extraConfig = '' - limit_except GET { deny all; } - proxy_buffering off; - gzip_comp_level 1; - access_log off; - ''; - }; - locations."/upload/" = { - proxyPass = "http://${config.services.ncps.server.addr}"; - basicAuthFile = config.age.secrets.nix-cache-push.path; - extraConfig = '' - client_max_body_size 0; - proxy_request_buffering off; - proxy_http_version 1.1; - proxy_read_timeout 3600s; - ''; + + age = { + secrets = { + influxdb-admin-password = { + file = ../../secrets/influxdb-admin-password.age; + owner = "influxdb2"; + group = "influxdb2"; + mode = "600"; + }; + influxdb-admin-token = { + file = ../../secrets/influxdb-admin-token.age; + owner = "influxdb2"; + group = "influxdb2"; + mode = "600"; + }; + influxdb-user-password = { + file = ../../secrets/influxdb-user-password.age; + owner = "influxdb2"; + group = "influxdb2"; + mode = "600"; + }; + garage_rpc = { + file = ../../secrets/garage_rpc_secret.age; + owner = "root"; + group = "garage-secrets"; + mode = "640"; + }; + garage_admin = { + file = ../../secrets/garage_admin_secret.age; + owner = "root"; + group = "garage-secrets"; + mode = "640"; + }; + garage_metrics = { + file = ../../secrets/garage_metrics_secret.age; + owner = "root"; + group = "garage-secrets"; + mode = "640"; + }; + tranquil-pds-env = { + file = ../../secrets/tranquil-pds-env.age; + owner = "tranquil-pds"; + group = "tranquil-pds"; + }; + acme = { + file = ../../secrets/porkbun-api-key.age; + owner = "root"; + group = "acme"; + }; + pounce-libera = { + file = ../../secrets/pounce-libera.age; + owner = "pounce"; + group = "pounce"; + mode = "600"; + }; + pounce-pine64 = { + file = ../../secrets/pounce-pine64.age; + owner = "pounce"; + group = "pounce"; + mode = "600"; + }; + pounce-tilde = { + file = ../../secrets/pounce-tilde.age; + owner = "pounce"; + group = "pounce"; + mode = "600"; + }; + pounce-libera-client-cert = { + file = ../../secrets/pounce-libera-client-cert.age; + owner = "pounce"; + group = "pounce"; + mode = "600"; + }; + pounce-libera-client-key = { + file = ../../secrets/pounce-libera-client-key.age; + owner = "pounce"; + group = "pounce"; + mode = "600"; + }; + pounce-legacy-client-cert = { + file = ../../secrets/pounce-legacy-client-cert.age; + owner = "pounce"; + group = "pounce"; + mode = "600"; + }; + nix-serve = { + file = ../../secrets/nix-serve-secret-key.age; + owner = "root"; + group = "root"; + }; + nix-cache-push = { + file = ../../secrets/nix-cache-push.age; + owner = "noah"; + group = "nas"; + }; + victoriapass = { + file = ../../secrets/victoria-secret.age; + owner = "root"; + group = "root"; + }; + victoriatraces-write-pass = { + file = ../../secrets/victoriatraces-write-pass.age; + owner = "root"; + group = "root"; + }; + opds-password = { + file = ../../secrets/opds-password.age; + owner = "noah"; + group = "nas"; + mode = "440"; + }; + pocket-id-encryption-key = { + file = ../../secrets/pocket-id-encryption-key.age; + owner = "pocket-id"; + group = "pocket-id"; + mode = "600"; + }; }; }; - virtualHosts."nixery.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - http2 = true; - locations."/".proxyPass = "http://nixery"; - }; - virtualHosts."knot.packetlost.dev" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - http2 = true; - locations."/" = { - proxyPass = "http://${config.services.tangled.knot.server.listenAddr}"; - proxyWebsockets = true; - }; - locations."/events" = { - proxyPass = "http://${config.services.tangled.knot.server.listenAddr}"; - extraConfig = '' - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $host; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - ''; + # Litterbox, collect my IRC logs + systemd = { + services = { + "litterbox@" = { + path = [ pkgs.litterbox ]; + serviceConfig = { + StartLimitIntervalSec = 5; + StartLimitBurst = 10; + Restart = "on-failure"; + RestartSec = "10s"; + Type = "simple"; + ExecStart = "${pkgs.litterbox}/bin/litterbox /srv/litterbox/%i.conf"; + ExecReload = "kill -USR1 $MAINPID"; + User = "noah"; + Group = "litterbox"; + }; + }; + + #"litterbox@libera.irc.packetlost.dev" = { + # overrideStrategy = "asDropin"; + # wantedBy = [ "multi-user.target" ]; + #}; + "update-downstream-src" = { + path = with pkgs; [ + rc + coreutils + git + openssh + ]; + script = "exec ${./scripts/update-src}"; + serviceConfig = { + Type = "oneshot"; + User = "noah"; + WorkingDirectory = "/srv/src"; + }; + }; + + garage.serviceConfig.SupplementaryGroups = "garage-secrets"; + tranquil-pds.serviceConfig = { + EnvironmentFile = config.age.secrets.tranquil-pds-env.path; + ReadWritePaths = [ + "/srv/shokuhou/applications/tranquil" + ]; + }; + koreader-sync-server = { + after = [ "redis-shared.service" ]; + requires = [ "redis-shared.service" ]; + }; + navidrome.serviceConfig = { + BindReadOnlyPaths = [ + "/srv/shokuhou/music" + ]; + }; }; - }; - virtualHosts."id.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - http2 = true; - locations."/".proxyPass = "http://localhost:1411/"; - }; - virtualHosts."pds.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - http2 = true; - locations."/" = { - proxyPass = "http://127.0.0.1:${toString config.services.tranquil-pds.settings.server.port}"; - proxyWebsockets = true; - extraConfig = '' - client_max_body_size 50000M; - proxy_read_timeout 600s; - proxy_send_timeout 600s; - send_timeout 600s; - ''; + timers = { + "update-downstream-src" = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "daily"; + Persistent = true; + }; + }; }; }; - virtualHosts."stats.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - http2 = true; - locations."/".proxyPass = "http://localhost:8086/"; - }; - virtualHosts."traces.ngp.computer" = { - http2 = true; - extraConfig = '' - allow 192.168.0.0/16; - allow 10.0.0.0/8; - allow 172.16.0.0/12; - allow 127.0.0.1; - allow ::1; - deny all; - ''; - locations."/" = { - proxyPass = "http://localhost:10428/"; - basicAuthFile = "/var/lib/nginx/victoriatraces.htpasswd"; - }; - locations."/insert/" = { - proxyPass = "http://localhost:10428/"; - basicAuthFile = "/var/lib/nginx/victoriatraces-insert.htpasswd"; + + # Containers and VMs + virtualisation = { + podman = { + enable = true; + dockerCompat = true; + defaultNetwork.settings.dns_enabled = true; }; }; - # give a name to the virtual host. It also becomes the server name. - virtualHosts."plex.packetlost.dev" = { - # Since we want a secure connection, we force SSL - forceSSL = true; - enableACME = true; - acmeRoot = null; - - # http2 can more performant for streaming: https://blog.cloudflare.com/introducing-http2/ - http2 = true; - - # Provide the ssl cert and key for the vhost - # These are filled in automatically with ACME - extraConfig = '' - - #Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause - send_timeout 100m; - - # Why this is important: https://blog.cloudflare.com/ocsp-stapling-how-cloudflare-just-made-ssl-30/ - ssl_stapling on; - ssl_stapling_verify on; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_prefer_server_ciphers on; - #Intentionally not hardened for security for player support and encryption video streams has a lot of overhead with something like AES-256-GCM-SHA384. - ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; - - # Forward real ip and host to Plex - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $server_addr; - proxy_set_header Referer $server_addr; - proxy_set_header Origin $server_addr; - - # Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. - gzip on; - gzip_vary on; - gzip_min_length 1000; - gzip_proxied any; - gzip_types text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml; - gzip_disable "MSIE [1-6]\."; - - # Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones. - # Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more - client_max_body_size 100M; - - # Plex headers - proxy_set_header X-Plex-Client-Identifier $http_x_plex_client_identifier; - proxy_set_header X-Plex-Device $http_x_plex_device; - proxy_set_header X-Plex-Device-Name $http_x_plex_device_name; - proxy_set_header X-Plex-Platform $http_x_plex_platform; - proxy_set_header X-Plex-Platform-Version $http_x_plex_platform_version; - proxy_set_header X-Plex-Product $http_x_plex_product; - proxy_set_header X-Plex-Token $http_x_plex_token; - proxy_set_header X-Plex-Version $http_x_plex_version; - proxy_set_header X-Plex-Nocache $http_x_plex_nocache; - proxy_set_header X-Plex-Provides $http_x_plex_provides; - proxy_set_header X-Plex-Device-Vendor $http_x_plex_device_vendor; - proxy_set_header X-Plex-Model $http_x_plex_model; + security.acme = { + acceptTerms = true; + defaults.email = "noah@packetlost.dev"; + certs = + pkgs.lib.genAttrs + [ + "plex.packetlost.dev" + "img.ngp.computer" + "books.ngp.computer" + "kosync.ngp.computer" + "knot.packetlost.dev" + "files.ngp.computer" + "foundry.ngp.computer" + "cache.ngp.computer" + "code.ngp.computer" + "photos.ngp.computer" + "jellyfin.packetlost.dev" + "id.ngp.computer" + "stats.ngp.computer" + "nixery.ngp.computer" + "pds.ngp.computer" + ] + (name: { + group = "httpd"; + dnsProvider = "porkbun"; + environmentFile = config.age.secrets.acme.path; + # Direct authoritative queries select IPv6, which the ISP drops. + extraLegoFlags = + if name == "books.ngp.computer" then + [ "--dns.propagation-disable-ans" ] + else if name == "kosync.ngp.computer" then + [ + "--dns.resolvers" + "1.1.1.1:53" + "--dns.propagation-disable-ans" + ] + else + [ ]; + }); + }; - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; + system.activationScripts.nginx-victoriatraces-htpasswd = '' + mkdir -p /var/lib/nginx + ${pkgs.apacheHttpd}/bin/htpasswd -nbB noah "$(cat ${config.age.secrets.victoriapass.path})" > /var/lib/nginx/victoriatraces.htpasswd + ${pkgs.apacheHttpd}/bin/htpasswd -nbB noah "$(cat ${config.age.secrets.victoriapass.path})" > /var/lib/nginx/victoriatraces-insert.htpasswd + ${pkgs.apacheHttpd}/bin/htpasswd -nbB publisher "$(cat ${config.age.secrets.victoriatraces-write-pass.path})" >> /var/lib/nginx/victoriatraces-insert.htpasswd + ''; - # Buffering off send to the client as soon as the data is received from Plex. - proxy_redirect off; - proxy_buffering off; - ''; + users.users.immich.extraGroups = [ + "video" + "render" + "nas" + ]; - locations."/" = { - recommendedProxySettings = false; - proxyPass = "http://localhost:32400/"; - }; - }; + users.users.pocket-id.extraGroups = [ "nas" ]; }; } diff --git a/host-specific/misaki/users.nix b/host-specific/misaki/users.nix index 32fbf9f..8c8e54b 100644 --- a/host-specific/misaki/users.nix +++ b/host-specific/misaki/users.nix @@ -1,7 +1,8 @@ -{ ... }: -{ - users.groups.nas.gid = 1001; - users.groups.httpd.gid = 1002; - users.groups.litterbox.gid = 1003; - users.groups.garage-secrets.gid = 1004; +_: { + users.groups = { + nas.gid = 1001; + httpd.gid = 1002; + litterbox.gid = 1003; + garage-secrets.gid = 1004; + }; } diff --git a/host-specific/odin/boot.nix b/host-specific/odin/boot.nix index a100fd3..7c94b32 100644 --- a/host-specific/odin/boot.nix +++ b/host-specific/odin/boot.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +_: { # Use the systemd-boot EFI boot loader. boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; diff --git a/host-specific/odin/gui.nix b/host-specific/odin/gui.nix index ded8e00..c655c29 100644 --- a/host-specific/odin/gui.nix +++ b/host-specific/odin/gui.nix @@ -31,11 +31,6 @@ let in { # Enable the X11 windowing system. - services.xserver = { - enable = true; - videoDrivers = [ "amdgpu" ]; - }; - # Fix for HIP libraries systemd.tmpfiles.rules = [ "L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}" @@ -50,14 +45,6 @@ in # Enable sound. security.rtkit.enable = true; - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - wireplumber.enable = true; - }; - # Graphics and parallel compute configuration hardware.graphics = { enable = true; @@ -93,24 +80,6 @@ in # Use greetd as the displaymanager #services.xserver.displayManager.greetd.enable = true; #services.xserver.displayManager.lightdm.enable = false; - services.displayManager.sddm.enable = true; - services.displayManager.defaultSession = "sway"; - services.displayManager.autoLogin = { - enable = true; - user = "noah"; - }; - - # i3, for when I need XOrg - services.xserver.windowManager.i3 = { - enable = true; - extraPackages = with pkgs; [ - dmenu - i3status - i3lock - i3blocks - ]; - }; - xdg.portal = { enable = true; wlr.enable = true; @@ -128,8 +97,38 @@ in "x-scheme-handler/https" = "org.firefox.firefox.desktop"; }; }; - services.dbus.enable = true; - services.gnome.gnome-keyring.enable = true; + services = { + xserver = { + enable = true; + videoDrivers = [ "amdgpu" ]; + windowManager.i3 = { + enable = true; + extraPackages = with pkgs; [ + dmenu + i3status + i3lock + i3blocks + ]; + }; + }; + pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + wireplumber.enable = true; + }; + displayManager = { + sddm.enable = true; + defaultSession = "sway"; + autoLogin = { + enable = true; + user = "noah"; + }; + }; + dbus.enable = true; + gnome.gnome-keyring.enable = true; + }; environment.systemPackages = with pkgs; [ wdisplays diff --git a/host-specific/odin/hardware-configuration.nix b/host-specific/odin/hardware-configuration.nix index e6df0fc..7ccedd3 100644 --- a/host-specific/odin/hardware-configuration.nix +++ b/host-specific/odin/hardware-configuration.nix @@ -14,46 +14,48 @@ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.kernelPackages = pkgs.linuxPackages_latest; - boot.initrd.availableKernelModules = [ - "nvme" - "xhci_pci" - "thunderbolt" - "usb_storage" - "usbhid" - "sd_mod" - "sdhci_pci" - ]; - boot.initrd.kernelModules = [ - "kvm-amd" - "amdgpu" - "nvme" - "xhci_pci" - "thunderbolt" - "usb_storage" - "usbhid" - "sd_mod" - "sdhci_pci" - ]; - boot.kernelModules = [ - "kvm-amd" - "amdgpu" - "nvme" - "xhci_pci" - "thunderbolt" - "usb_storage" - "usbhid" - "sd_mod" - "sdhci_pci" - ]; + #boot.extraModulePackages = with config.boot.kernelPackages; [ ]; + boot = { + kernelPackages = pkgs.linuxPackages_latest; + initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "thunderbolt" + "usb_storage" + "usbhid" + "sd_mod" + "sdhci_pci" + ]; + initrd.kernelModules = [ + "kvm-amd" + "amdgpu" + "nvme" + "xhci_pci" + "thunderbolt" + "usb_storage" + "usbhid" + "sd_mod" + "sdhci_pci" + ]; + kernelModules = [ + "kvm-amd" + "amdgpu" + "nvme" + "xhci_pci" + "thunderbolt" + "usb_storage" + "usbhid" + "sd_mod" + "sdhci_pci" + ]; + kernelParams = [ ]; + }; virtualisation.libvirtd = { enable = true; qemu = { runAsRoot = false; }; }; - #boot.extraModulePackages = with config.boot.kernelPackages; [ ]; - boot.kernelParams = [ ]; hardware.enableRedistributableFirmware = true; diff --git a/host-specific/odin/networking.nix b/host-specific/odin/networking.nix index dd1807d..3b649cd 100644 --- a/host-specific/odin/networking.nix +++ b/host-specific/odin/networking.nix @@ -4,28 +4,30 @@ # Pick only one of the below networking options. # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. # networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. - networking.hostName = "odin"; + networking = { + hostName = "odin"; + tempAddresses = "disabled"; + useNetworkd = true; + }; # I like systemd-networkd - systemd.network.enable = true; - systemd.network.networks."50-enp1s0" = { - matchConfig.Name = "enp1s0"; - networkConfig = { - DHCP = "yes"; - MulticastDNS = "yes"; + systemd.network = { + enable = true; + networks."50-enp1s0" = { + matchConfig.Name = "enp1s0"; + networkConfig = { + DHCP = "yes"; + MulticastDNS = "yes"; + }; }; - }; - systemd.network.networks."50-wlp2s0" = { - matchConfig.Name = "wlp2s0"; - networkConfig = { - DHCP = "yes"; - MulticastDNS = "yes"; + networks."50-wlp2s0" = { + matchConfig.Name = "wlp2s0"; + networkConfig = { + DHCP = "yes"; + MulticastDNS = "yes"; + }; + linkConfig.RequiredForOnline = "no"; }; - linkConfig.RequiredForOnline = "no"; }; - - networking.tempAddresses = "disabled"; - - networking.useNetworkd = true; # TODO: static IP @ 192.168.1.6 # Configure network proxy if necessary diff --git a/host-specific/odin/services.nix b/host-specific/odin/services.nix index df55ae3..84ca767 100644 --- a/host-specific/odin/services.nix +++ b/host-specific/odin/services.nix @@ -6,12 +6,6 @@ }: let nixeryPackages = import ../../overlays/nixery.nix (pkgs // nixeryPackages) pkgs; - celldSource = pkgs.fetchFromGitHub { - owner = "denoland"; - repo = "celld"; - rev = "v0.1.0"; - hash = "sha256-Iew3/ugHftS1Ui6tiVRPj3FguYmGx9vwMfS6pY00CWQ="; - }; in { imports = [ @@ -36,233 +30,235 @@ in systemd.tmpfiles.rules = [ "d /home/noah/repos/noah 0750 noah noah -" ]; - age.secrets.opencode-password = { - file = ../../secrets/opencode-password.age; - owner = "noah"; - group = "noah"; - }; - - services.opencode-v2 = { - hostname = "192.168.1.6"; - group = "noah"; - passwordFile = config.age.secrets.opencode-password.path; - }; - - services.tailscale = { - extraSetFlags = [ - "--ssh" - ]; - }; - - services.redis.servers."" = { - enable = true; - }; - - # Instances share the module-managed Garage service and credentials. Each - # instance gets a bucket matching its name. - #services.celld.instances.default = { - # listenAddress = "0.0.0.0"; - # port = 8082; - # internalListenAddress = "0.0.0.0"; - # internalPort = 8083; - # advertise = "odin:8083"; - # projects.counter = { - # root = celldSource; - # config = "examples/counter"; - # }; - # primaryProject = "counter"; - #}; - - services.microcosm.constellation = { - enable = false; - jetstream = "us-east-1"; - bind = "127.0.0.1:6789"; - backend = "rocks"; - logLevel = "debug"; - metrics = { - enable = true; - bind = "127.0.0.1:8765"; + security.acme = { + acceptTerms = true; + defaults.email = "noah@packetlost.dev"; + certs = { + "spindle.packetlost.dev" = { + group = config.services.nginx.group; + dnsProvider = "porkbun"; + environmentFile = config.age.secrets.acme.path; + }; + "odin.ngp.computer" = { + group = config.services.nginx.group; + dnsProvider = "porkbun"; + environmentFile = config.age.secrets.acme.path; + }; }; }; - services.nixery = { - enable = true; - package = nixeryPackages.nixery; - openFirewall = false; - port = 8080; - storage.backend = "filesystem"; - storage.path = "/var/lib/nixery/storage"; - packageSource = { - type = "path"; - path = pkgs.path; + virtualisation = { + podman = { + enable = false; + dockerCompat = true; + defaultNetwork.settings.dns_enabled = true; + dockerSocket.enable = true; }; - }; - - services.total-recall = { - enable = true; - #listenAddress = "100.127.136.117"; - listenAddress = "[::]"; - port = 3030; - openFirewall = true; - oidc = { - issuer = "https://id.ngp.computer"; - audience = "total-recall"; - browserClientId = "total-recall"; - browserRedirectUri = "https://odin.ngp.computer/auth/callback"; + docker = { + enable = true; + storageDriver = "overlay2"; }; - mcpAllowedHosts = [ - "192.168.1.6" - "100.127.136.117" - "100.127.136.117:3030" - "odin.ngp.computer" - "odin.tail2d94b.ts.net" - "odin.tail2d94b.ts.net:3030" - ]; }; - services.nginx = { - enable = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - - virtualHosts."nixery.ngp.computer" = { - locations."/".proxyPass = "http://localhost:${toString config.services.nixery.port}"; + age.secrets = { + opencode-password = { + file = ../../secrets/opencode-password.age; + owner = "noah"; + group = "noah"; }; - virtualHosts."odin.ngp.computer" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - locations."/".proxyPass = "http://localhost:${toString config.services.total-recall.port}"; + acme = { + file = ../../secrets/porkbun-api-key.age; + owner = "root"; + group = "acme"; }; - virtualHosts."spindle.packetlost.dev" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - locations."/" = { - proxyPass = "http://localhost:6555"; - proxyWebsockets = true; - }; + github_actions_token.file = ../../secrets/github-actions-token.age; + buildkite-agent-token = { + file = ../../secrets/buildkite-agent-token.age; + owner = "buildkite-agent-default"; }; }; - age.secrets.acme = { - file = ../../secrets/porkbun-api-key.age; - owner = "root"; - group = "acme"; - }; + services = { + opencode-v2 = { + hostname = "192.168.1.6"; + group = "noah"; + passwordFile = config.age.secrets.opencode-password.path; + }; - security.acme = { - acceptTerms = true; - defaults.email = "noah@packetlost.dev"; - certs."spindle.packetlost.dev" = { - group = config.services.nginx.group; - dnsProvider = "porkbun"; - environmentFile = config.age.secrets.acme.path; + tailscale = { + extraSetFlags = [ + "--ssh" + ]; }; - certs."odin.ngp.computer" = { - group = config.services.nginx.group; - dnsProvider = "porkbun"; - environmentFile = config.age.secrets.acme.path; + + redis.servers."" = { + enable = true; }; - }; - # Containers and VMs - virtualisation = { - podman = { + # Instances share the module-managed Garage service and credentials. Each + # instance gets a bucket matching its name. + #services.celld.instances.default = { + # listenAddress = "0.0.0.0"; + # port = 8082; + # internalListenAddress = "0.0.0.0"; + # internalPort = 8083; + # advertise = "odin:8083"; + # projects.counter = { + # root = celldSource; + # config = "examples/counter"; + # }; + # primaryProject = "counter"; + #}; + + microcosm.constellation = { enable = false; - dockerCompat = true; - defaultNetwork.settings.dns_enabled = true; - dockerSocket.enable = true; + jetstream = "us-east-1"; + bind = "127.0.0.1:6789"; + backend = "rocks"; + logLevel = "debug"; + metrics = { + enable = true; + bind = "127.0.0.1:8765"; + }; }; - docker = { + + nixery = { enable = true; - storageDriver = "overlay2"; + package = nixeryPackages.nixery; + openFirewall = false; + port = 8080; + storage.backend = "filesystem"; + storage.path = "/var/lib/nixery/storage"; + packageSource = { + type = "path"; + inherit (pkgs) path; + }; }; - }; - services.tangled.spindle = { - enable = true; - server = { - hostname = "spindle.packetlost.dev"; - owner = "did:plc:hjp23blu4y7bgf7zrzhzdemi"; + total-recall = { + enable = true; + #listenAddress = "100.127.136.117"; + listenAddress = "[::]"; + port = 3030; + openFirewall = true; + oidc = { + issuer = "https://id.ngp.computer"; + audience = "total-recall"; + browserClientId = "total-recall"; + browserRedirectUri = "https://odin.ngp.computer/auth/callback"; + }; + mcpAllowedHosts = [ + "192.168.1.6" + "100.127.136.117" + "100.127.136.117:3030" + "odin.ngp.computer" + "odin.tail2d94b.ts.net" + "odin.tail2d94b.ts.net:3030" + ]; + }; + + nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + + virtualHosts = { + "nixery.ngp.computer" = { + locations."/".proxyPass = "http://localhost:${toString config.services.nixery.port}"; + }; + "odin.ngp.computer" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + locations."/".proxyPass = "http://localhost:${toString config.services.total-recall.port}"; + }; + "spindle.packetlost.dev" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + locations."/" = { + proxyPass = "http://localhost:6555"; + proxyWebsockets = true; + }; + }; + }; }; - pipelines = { - nixery.nixery = "localhost:${toString config.services.nixery.port}"; - workflowTimeout = "2h"; - logBucket = ""; - nixCache = { - readUrls = [ "https://cache.ngp.computer" ]; - trustedPublicKeys = [ - "misaki.packetlost.dev:y5Z/utaVBozpL0UAbUQDWLjpm2sVMOoKzyG76n/167A=" - ]; + tangled.spindle = { + enable = true; + server = { + hostname = "spindle.packetlost.dev"; + owner = "did:plc:hjp23blu4y7bgf7zrzhzdemi"; }; - microvm = { - limits = { - total = { - memoryMiB = 16384; - vcpus = 8; - diskMiB = 81920; + pipelines = { + nixery.nixery = "localhost:${toString config.services.nixery.port}"; + workflowTimeout = "2h"; + logBucket = ""; + nixCache = { + readUrls = [ "https://cache.ngp.computer" ]; + trustedPublicKeys = [ + "misaki.packetlost.dev:y5Z/utaVBozpL0UAbUQDWLjpm2sVMOoKzyG76n/167A=" + ]; + }; + microvm = { + limits = { + total = { + memoryMiB = 16384; + vcpus = 8; + diskMiB = 81920; + }; + workflow = { + memoryMiB = 8192; + vcpus = 4; + diskMiB = 40960; + }; }; - workflow = { - memoryMiB = 8192; - vcpus = 4; - diskMiB = 40960; + cgroup = { + enable = true; + pidsMax = 4096; + swapMaxMiB = 0; + supervisorMinMiB = 512; }; }; - cgroup = { - enable = true; - pidsMax = 4096; - swapMaxMiB = 0; - supervisorMinMiB = 512; - }; }; }; - }; - age.secrets.github_actions_token = { - file = ../../secrets/github-actions-token.age; - }; - services.github-runners.odin = { - enable = false; - tokenFile = config.age.secrets.github_actions_token.path; - extraLabels = [ - "large" - ]; - extraPackages = [ - pkgs.git-lfs - ]; - }; + github-runners.odin = { + enable = false; + tokenFile = config.age.secrets.github_actions_token.path; + extraLabels = [ + "large" + ]; + extraPackages = [ + pkgs.git-lfs + ]; + }; - age.secrets.buildkite-agent-token = { - file = ../../secrets/buildkite-agent-token.age; - owner = "buildkite-agent-default"; - }; - services.buildkite-agents.default = { - tokenPath = config.age.secrets.buildkite-agent-token.path; - name = "%hostname-%n"; - tags = { - queue = "default"; - nixos = "true"; - docker = "true"; + buildkite-agents.default = { + tokenPath = config.age.secrets.buildkite-agent-token.path; + name = "%hostname-%n"; + tags = { + queue = "default"; + nixos = "true"; + docker = "true"; + }; + extraGroups = [ "docker" ]; + runtimePackages = with pkgs; [ + bash + docker-client + git + git-lfs + gnutar + gzip + nix + ]; + }; + centralLogging = { + enable = true; + collector = "client"; }; - extraGroups = [ "docker" ]; - runtimePackages = with pkgs; [ - bash - docker-client - git - git-lfs - gnutar - gzip - nix - ]; }; nix.settings.trusted-users = [ "buildkite-agent-default" ]; - - services.centralLogging = { - enable = true; - collector = "client"; - }; } diff --git a/host-specific/odin/valheim.nix b/host-specific/odin/valheim.nix index c72b72d..0314a7a 100644 --- a/host-specific/odin/valheim.nix +++ b/host-specific/odin/valheim.nix @@ -1,7 +1,4 @@ -{ - ... -}: -{ +_: { services.valheim = { enable = false; serverName = "ngp's Valheim server"; diff --git a/host-specific/odin/xrdp-macos9.nix b/host-specific/odin/xrdp-macos9.nix index 8c85733..245c616 100644 --- a/host-specific/odin/xrdp-macos9.nix +++ b/host-specific/odin/xrdp-macos9.nix @@ -27,15 +27,16 @@ in ngp.macos9PlatinumTheme.enable = true; - services.xserver.desktopManager.lxqt.enable = true; - services.xscreensaver.enable = false; - security.pam.services.xscreensaver.enable = false; - - services.xrdp = { - enable = true; - openFirewall = true; - defaultWindowManager = toString xrdpLxqtSession; + services = { + xserver.desktopManager.lxqt.enable = true; + xscreensaver.enable = false; + xrdp = { + enable = true; + openFirewall = true; + defaultWindowManager = toString xrdpLxqtSession; + }; }; + security.pam.services.xscreensaver.enable = false; programs.dconf.enable = true; diff --git a/host-specific/othinus/boot.nix b/host-specific/othinus/boot.nix index a100fd3..7c94b32 100644 --- a/host-specific/othinus/boot.nix +++ b/host-specific/othinus/boot.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +_: { # Use the systemd-boot EFI boot loader. boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; diff --git a/host-specific/othinus/configuration.nix b/host-specific/othinus/configuration.nix index 815e3f2..fc445e7 100644 --- a/host-specific/othinus/configuration.nix +++ b/host-specific/othinus/configuration.nix @@ -1,4 +1,4 @@ -{ lib, inputs, ... }: +{ lib, ... }: { imports = [ ../../modules/opencode-service.nix diff --git a/host-specific/othinus/disko.nix b/host-specific/othinus/disko.nix index 4d59000..fdf9f63 100644 --- a/host-specific/othinus/disko.nix +++ b/host-specific/othinus/disko.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +_: { disko.devices = { disk.main = { type = "disk"; diff --git a/host-specific/othinus/hardware-configuration.nix b/host-specific/othinus/hardware-configuration.nix index 9e2ee8b..b1461cf 100644 --- a/host-specific/othinus/hardware-configuration.nix +++ b/host-specific/othinus/hardware-configuration.nix @@ -13,17 +13,19 @@ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.kernelPackages = pkgs.linuxPackages_latest; - boot.initrd.availableKernelModules = [ - "nvme" - "xhci_pci" - "usb_storage" - "usbhid" - "sd_mod" - ]; - boot.initrd.kernelModules = [ "kvm-amd" ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot = { + kernelPackages = pkgs.linuxPackages_latest; + initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "usb_storage" + "usbhid" + "sd_mod" + ]; + initrd.kernelModules = [ "kvm-amd" ]; + kernelModules = [ "kvm-amd" ]; + extraModulePackages = [ ]; + }; hardware.enableRedistributableFirmware = true; diff --git a/host-specific/othinus/networking.nix b/host-specific/othinus/networking.nix index 234b878..5b76281 100644 --- a/host-specific/othinus/networking.nix +++ b/host-specific/othinus/networking.nix @@ -1,6 +1,9 @@ -{ ... }: -{ - networking.hostName = "othinus"; +_: { + networking = { + hostName = "othinus"; + tempAddresses = "disabled"; + useNetworkd = true; + }; systemd.network.enable = true; systemd.network.networks."50-enp2s0" = { @@ -11,9 +14,6 @@ }; }; - networking.tempAddresses = "disabled"; - networking.useNetworkd = true; - networking.firewall = { enable = true; allowPing = true; diff --git a/host-specific/othinus/virtualisation.nix b/host-specific/othinus/virtualisation.nix index 30515f7..49b04df 100644 --- a/host-specific/othinus/virtualisation.nix +++ b/host-specific/othinus/virtualisation.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +_: { virtualisation = { libvirtd = { enable = true; diff --git a/host-specific/shizuri/boot.nix b/host-specific/shizuri/boot.nix index aad94fb..ee4eb05 100644 --- a/host-specific/shizuri/boot.nix +++ b/host-specific/shizuri/boot.nix @@ -1,20 +1,21 @@ -{ ... }: -{ +_: { # Use the systemd-boot EFI boot loader. - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; + boot = { + loader.systemd-boot.enable = true; + loader.efi.canTouchEfiVariables = true; - # Strix Halo (gfx1151) KFD currently rejects AMDKFD_IOC_CREATE_QUEUE with - # cwsr enabled on this kernel, breaking every HIP launch with - # HSA_STATUS_ERROR_OUT_OF_RESOURCES. Disabling compute wave save/restore - # works around it until the kernel-side path stabilizes. - # The firmware UMA carveout is set to its 512 MiB minimum, leaving system - # memory available through GTT for resident models and ROCm graph state. - boot.kernelParams = [ - "amdgpu.cwsr_enable=0" - "amd_iommu=off" - "amdgpu.gttsize=126976" - "ttm.pages_limit=32505856" - "ttm.page_pool_size=32505856" - ]; + # Strix Halo (gfx1151) KFD currently rejects AMDKFD_IOC_CREATE_QUEUE with + # cwsr enabled on this kernel, breaking every HIP launch with + # HSA_STATUS_ERROR_OUT_OF_RESOURCES. Disabling compute wave save/restore + # works around it until the kernel-side path stabilizes. + # The firmware UMA carveout is set to its 512 MiB minimum, leaving system + # memory available through GTT for resident models and ROCm graph state. + kernelParams = [ + "amdgpu.cwsr_enable=0" + "amd_iommu=off" + "amdgpu.gttsize=126976" + "ttm.pages_limit=32505856" + "ttm.page_pool_size=32505856" + ]; + }; } diff --git a/host-specific/shizuri/gui.nix b/host-specific/shizuri/gui.nix index 4e7190f..823c39f 100644 --- a/host-specific/shizuri/gui.nix +++ b/host-specific/shizuri/gui.nix @@ -7,11 +7,6 @@ let in { # Enable the X11 windowing system. - services.xserver = { - enable = true; - videoDrivers = [ "amdgpu" ]; - }; - # Fix for HIP libraries systemd.tmpfiles.rules = [ "L+ /opt/rocm/hip - - - - ${rocm.clr}" @@ -20,41 +15,13 @@ in # ROCm/HSA on RDNA3+ needs a large memlock budget to bring up its execution # queues; the 8 MiB default produces HSA_STATUS_ERROR_OUT_OF_RESOURCES at # first kernel launch. - security.pam.loginLimits = [ - { - domain = "*"; - type = "soft"; - item = "memlock"; - value = "unlimited"; - } - { - domain = "*"; - type = "hard"; - item = "memlock"; - value = "unlimited"; - } - ]; - # Configure keymap in X11 - services.xserver.xkb = { - layout = "us"; - variant = ""; - }; # services.xserver.xkb.options = "eurosign:e,caps:escape"; # Enable CUPS to print documents. # services.printing.enable = true; # Enable sound. - security.rtkit.enable = true; - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - wireplumber.enable = true; - }; - # Graphics and parallel compute configuration hardware.graphics = { enable = true; @@ -79,7 +46,24 @@ in ]; # Polkit is a dependency of Sway. It's responsible for handling security policies - security.polkit.enable = true; + security = { + pam.loginLimits = [ + { + domain = "*"; + type = "soft"; + item = "memlock"; + value = "unlimited"; + } + { + domain = "*"; + type = "hard"; + item = "memlock"; + value = "unlimited"; + } + ]; + rtkit.enable = true; + polkit.enable = true; + }; # Enable the sway window manager programs.sway = { @@ -90,27 +74,12 @@ in # Use greetd as the displaymanager #services.xserver.displayManager.greetd.enable = true; - services.xserver.displayManager.lightdm.enable = false; - #services.displayManager.sddm.enable = true; #services.displayManager.defaultSession = "sway"; #services.displayManager.autoLogin = { # enable = true; # user = "noah"; #}; - services.xserver.desktopManager.xfce.enable = false; - - # i3, for when I need XOrg - services.xserver.windowManager.i3 = { - enable = false; - extraPackages = with pkgs; [ - dmenu - i3status - i3lock - i3blocks - ]; - }; - xdg.portal = { enable = true; wlr.enable = true; @@ -128,8 +97,36 @@ in "x-scheme-handler/https" = "org.firefox.firefox.desktop"; }; }; - services.dbus.enable = true; - services.gnome.gnome-keyring.enable = true; + services = { + xserver = { + enable = true; + videoDrivers = [ "amdgpu" ]; + xkb = { + layout = "us"; + variant = ""; + }; + displayManager.lightdm.enable = false; + desktopManager.xfce.enable = false; + windowManager.i3 = { + enable = false; + extraPackages = with pkgs; [ + dmenu + i3status + i3lock + i3blocks + ]; + }; + }; + pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + wireplumber.enable = true; + }; + dbus.enable = true; + gnome.gnome-keyring.enable = true; + }; environment.systemPackages = [ rocm.clr diff --git a/host-specific/shizuri/hardware-configuration.nix b/host-specific/shizuri/hardware-configuration.nix index db5bcd7..e391e7c 100644 --- a/host-specific/shizuri/hardware-configuration.nix +++ b/host-specific/shizuri/hardware-configuration.nix @@ -14,19 +14,21 @@ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.kernelPackages = pkgs.linuxPackages_latest; - boot.initrd.availableKernelModules = [ - "nvme" - "xhci_pci" - "thunderbolt" - "usb_storage" - "usbhid" - "uas" - "sd_mod" - ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot = { + kernelPackages = pkgs.linuxPackages_latest; + initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "thunderbolt" + "usb_storage" + "usbhid" + "uas" + "sd_mod" + ]; + initrd.kernelModules = [ ]; + kernelModules = [ "kvm-amd" ]; + extraModulePackages = [ ]; + }; # Bluetooth / wireless configuration hardware.bluetooth = { @@ -51,26 +53,28 @@ }; }; - fileSystems."/" = { - device = "/dev/disk/by-uuid/9a7cbffe-6c10-4220-bb99-4dcea8181dcc"; - fsType = "ext4"; - }; + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/9a7cbffe-6c10-4220-bb99-4dcea8181dcc"; + fsType = "ext4"; + }; - fileSystems."/boot" = { - device = "/dev/disk/by-uuid/9AC5-62C3"; - fsType = "vfat"; - options = [ - "fmask=0077" - "dmask=0077" - ]; - }; + "/boot" = { + device = "/dev/disk/by-uuid/9AC5-62C3"; + fsType = "vfat"; + options = [ + "fmask=0077" + "dmask=0077" + ]; + }; - swapDevices = [ { device = "/dev/disk/by-uuid/a19d8fad-d8d2-4bbe-a233-e645020419ff"; } ]; - fileSystems."/srv/mugino" = { - device = "/dev/disk/by-uuid/d832dd9f-1fbb-4ca7-9097-0ba329b838af"; - fsType = "ext4"; + "/srv/mugino" = { + device = "/dev/disk/by-uuid/d832dd9f-1fbb-4ca7-9097-0ba329b838af"; + fsType = "ext4"; + }; }; + swapDevices = [ { device = "/dev/disk/by-uuid/a19d8fad-d8d2-4bbe-a233-e645020419ff"; } ]; # Enables DHCP on each ethernet and wireless interface. In case of scripted networking # (the default) this is the recommended approach. When using systemd-networkd it's # still possible to use this option, but it's recommended to use it in conjunction diff --git a/host-specific/shizuri/networking.nix b/host-specific/shizuri/networking.nix index 7513f36..ea61e8f 100644 --- a/host-specific/shizuri/networking.nix +++ b/host-specific/shizuri/networking.nix @@ -1,10 +1,13 @@ -{ ... }: -{ +_: { # networking.hostName = "nixos"; # Define your hostname. # Pick only one of the below networking options. # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. # networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. - networking.hostName = "shizuri"; + networking = { + hostName = "shizuri"; + tempAddresses = "disabled"; + useNetworkd = true; + }; # I like systemd-networkd systemd.network.enable = true; systemd.network.networks."50-wlp2s0" = { @@ -13,9 +16,6 @@ linkConfig.RequiredForOnline = "no"; }; - networking.tempAddresses = "disabled"; - - networking.useNetworkd = true; # TODO: static IP @ 192.168.1.2 # Configure network proxy if necessary diff --git a/host-specific/shizuri/packages.nix b/host-specific/shizuri/packages.nix index a2ce705..46a8ead 100644 --- a/host-specific/shizuri/packages.nix +++ b/host-specific/shizuri/packages.nix @@ -62,16 +62,10 @@ let # bash script to let dbus know about important env variables and name = "configure-gtk"; destination = "/bin/configure-gtk"; executable = true; - text = - let - # TODO: figure out why these bindings exist or where they're used - schema = pkgs.gsettings-desktop-schemas; - datadir = "${schema}/share/gsettings-schemas/${schema.name}"; - in - '' - 6 gnome_schema=org.gnome.desktop.interface - gsettings set $gnome_schema gtk-theme 'Dracula' - ''; + text = '' + 6 gnome_schema=org.gnome.desktop.interface + gsettings set $gnome_schema gtk-theme 'Dracula' + ''; }; in { @@ -133,36 +127,42 @@ in documentation.dev.enable = true; # Fix dynamically linked libraries for unpackaged binaries - programs.nix-ld = { - enable = true; - libraries = with pkgs; [ - # Add missing dynamic libraries for unpackaged programs HERE - # NOT in environment.systemPackages - zlib - openssl - sqlite - libunwind - libglvnd - libclang - systemdLibs - ]; - }; - programs.nix-index = { - enable = true; - enableFishIntegration = true; - enableBashIntegration = false; - enableZshIntegration = false; - }; + programs = { + nix-ld = { + enable = true; + libraries = with pkgs; [ + # Add missing dynamic libraries for unpackaged programs HERE + # NOT in environment.systemPackages + zlib + openssl + sqlite + libunwind + libglvnd + libclang + systemdLibs + ]; + }; + nix-index = { + enable = true; + enableFishIntegration = true; + enableBashIntegration = false; + enableZshIntegration = false; + }; - programs.steam = { - enable = true; - remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play - dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server - localNetworkGameTransfers.openFirewall = true; # Open ports in the firewall for Steam Local Network Game Transfers - }; - programs.gamescope = { - enable = true; - capSysNice = true; + steam = { + enable = true; + remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play + dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server + localNetworkGameTransfers.openFirewall = true; # Open ports in the firewall for Steam Local Network Game Transfers + }; + gamescope = { + enable = true; + capSysNice = true; + }; + appimage = { + enable = true; + binfmt = true; + }; }; # Boot directly into Steam Big Picture on locally connected displays. xRDP # keeps its own LXQt session via services.xrdp.defaultWindowManager. @@ -181,11 +181,6 @@ in }; }; - programs.appimage = { - enable = true; - binfmt = true; - }; - # Run other bins in QEMU boot.binfmt.emulatedSystems = [ "aarch64-linux" @@ -195,23 +190,25 @@ in systemd.tmpfiles.rules = [ "L+ /var/lib/qemu/firmware - - - - ${pkgs.qemu}/share/qemu/firmware" ]; # Logseq uses an ancient version of Electron, so we enable that - nixpkgs.config.permittedInsecurePackages = [ "electron-25.9.0" ]; - - # I don't care too much about unfree - nixpkgs.config.allowUnfree = true; - # Whitelist some unfree packages - nixpkgs.config.allowUnfreePredicate = - pkg: - builtins.elem (lib.getName pkg) [ - "discord" - "obsidian" - "unstable.obsidian" - "tailscale" - "google-chrome" - "slack" - "steam" - "steam-original" - "steam-unwrapped" - "steam-run" - ]; + nixpkgs.config = { + permittedInsecurePackages = [ "electron-25.9.0" ]; + + # I don't care too much about unfree + allowUnfree = true; + # Whitelist some unfree packages + allowUnfreePredicate = + pkg: + builtins.elem (lib.getName pkg) [ + "discord" + "obsidian" + "unstable.obsidian" + "tailscale" + "google-chrome" + "slack" + "steam" + "steam-original" + "steam-unwrapped" + "steam-run" + ]; + }; } diff --git a/host-specific/shizuri/services.nix b/host-specific/shizuri/services.nix index 17779d9..edb45af 100644 --- a/host-specific/shizuri/services.nix +++ b/host-specific/shizuri/services.nix @@ -1,69 +1,73 @@ { - config, - pkgs, - inputs, ... }: { imports = [ ../../modules/opencode-service.nix ]; # OpenCode listens on TCP port 4096. - services.opencode-v2 = { - hostname = "0.0.0.0"; - port = 4096; - openFirewall = true; - }; - - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - programs.gnupg.agent = { - enable = true; - enableSSHSupport = false; - }; + services = { + opencode-v2 = { + hostname = "0.0.0.0"; + port = 4096; + openFirewall = true; + }; - # Enable the OpenSSH daemon. - services.openssh = { - enable = true; - settings.X11Forwarding = true; - }; + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # Enable the OpenSSH daemon. + openssh = { + enable = true; + settings.X11Forwarding = true; + }; - # Rust desk, remote desktop - services.rustdesk-server = { - enable = true; - openFirewall = true; - signal = { + # Rust desk, remote desktop + rustdesk-server = { enable = true; - relayHosts = [ - "shizuri.tail2d94b.ts.net" - ]; + openFirewall = true; + signal = { + enable = true; + relayHosts = [ "shizuri.tail2d94b.ts.net" ]; + }; + relay.enable = true; }; - relay.enable = true; - }; - # Smart Card daemon - services.pcscd.enable = true; + # Smart Card daemon + pcscd.enable = true; - # This option is for enabling the bolt daemon for managing Thunderbolt/USB4 Devices. - services.hardware.bolt.enable = true; + # This option is for enabling the bolt daemon for managing Thunderbolt/USB4 Devices. + fwupd.enable = true; - services.fwupd.enable = true; + tailscale.permitCertUid = "caddy"; + caddy = { + enable = true; + openFirewall = true; + virtualHosts = { + "shizuri.tail2d94b.ts.net".extraConfig = '' + reverse_proxy 127.0.0.1:19091 + ''; + "shizuri.local:80".extraConfig = '' + reverse_proxy 127.0.0.1:1234 + ''; + "shizuri.packetlost.dev:80".extraConfig = '' + reverse_proxy 127.0.0.1:1234 + ''; + }; + }; - services.tailscale.permitCertUid = "caddy"; - services.caddy = { + centralLogging = { + enable = true; + collector = "client"; + }; + }; + + programs.gnupg.agent = { enable = true; - openFirewall = true; - virtualHosts."shizuri.tail2d94b.ts.net".extraConfig = '' - reverse_proxy 127.0.0.1:19091 - ''; - virtualHosts."shizuri.local:80".extraConfig = '' - reverse_proxy 127.0.0.1:1234 - ''; - virtualHosts."shizuri.packetlost.dev:80".extraConfig = '' - reverse_proxy 127.0.0.1:1234 - ''; + enableSSHSupport = false; }; + services.hardware.bolt.enable = true; + # Containers and VMs virtualisation = { podman = { @@ -77,9 +81,4 @@ storageDriver = "overlay2"; }; }; - - services.centralLogging = { - enable = true; - collector = "client"; - }; } diff --git a/host-specific/touma-wsl/configuration.nix b/host-specific/touma-wsl/configuration.nix index e0feced..28c2a74 100644 --- a/host-specific/touma-wsl/configuration.nix +++ b/host-specific/touma-wsl/configuration.nix @@ -2,8 +2,6 @@ config, lib, pkgs, - inputs, - system, ... }: { @@ -21,32 +19,34 @@ networking.hostName = "touma-wsl-nixos"; # Enable mDNS resolution and advertisement for .local names - services.avahi = { - enable = true; - nssmdns4 = true; - openFirewall = true; - publish = { - enable = true; - addresses = true; - }; - }; - # Use glibc nscd so NSS mDNS modules (avahi/nss-mdns) work for hosts. - services.nscd.enableNsncd = false; - services.nscd.config = - lib.replaceStrings - [ "enable-cache hosts yes" ] - [ "enable-cache hosts no" ] - (builtins.readFile "${pkgs.path}/nixos/modules/services/system/nscd.conf"); - # glibc falls back to loading NSS modules directly when nscd cannot proxy an # mDNS lookup. Expose the NixOS NSS module path to interactive WSL sessions. environment.sessionVariables.LD_LIBRARY_PATH = config.system.nssModules.path; - services.openssh.enable = true; - - services.centralLogging = { - enable = true; - collector = "client"; + services = { + avahi = { + enable = true; + nssmdns4 = true; + openFirewall = true; + publish = { + enable = true; + addresses = true; + }; + }; + # Use glibc nscd so NSS mDNS modules (avahi/nss-mdns) work for hosts. + nscd = { + enableNsncd = false; + config = + lib.replaceStrings + [ "enable-cache hosts yes" ] + [ "enable-cache hosts no" ] + (builtins.readFile "${pkgs.path}/nixos/modules/services/system/nscd.conf"); + }; + openssh.enable = true; + centralLogging = { + enable = true; + collector = "client"; + }; }; # Fix dynamically linked libraries for unpackaged binaries diff --git a/host-specific/touma-wsl/hardware-configuration.nix b/host-specific/touma-wsl/hardware-configuration.nix index c915eb0..958608a 100644 --- a/host-specific/touma-wsl/hardware-configuration.nix +++ b/host-specific/touma-wsl/hardware-configuration.nix @@ -1 +1 @@ -{ ... }: { } +_: { } diff --git a/modules/home/core.nix b/modules/home/core.nix index de2872e..57fd3a9 100644 --- a/modules/home/core.nix +++ b/modules/home/core.nix @@ -33,252 +33,255 @@ in "${config.home.homeDirectory}/.ssh/id_ed25519_terminus" "${config.home.homeDirectory}/.ssh/id_ed25519" ]; - programs.home-manager.enable = true; - programs.direnv = { - enable = true; - nix-direnv.enable = true; - }; - programs.nix-index = { - enable = true; - enableFishIntegration = true; - }; - programs.fzf = { - enable = true; - enableFishIntegration = true; - }; - programs.pistol.enable = true; - programs.neovim = { - package = neovim-unwrapped; - enable = true; - defaultEditor = true; - withRuby = true; - withNodeJs = true; - withPython3 = true; - extraPackages = with pkgs; [ - unstable.fzf - unstable.ripgrep - luarocks - unstable.tree-sitter - ]; - }; - programs.helix = { - enable = true; - settings = { - theme = "everforest_dark"; - editor.cursor-shape = { - normal = "block"; - insert = "bar"; - select = "underline"; - }; + programs = { + home-manager.enable = true; + direnv = { + enable = true; + nix-direnv.enable = true; }; - languages.language = [ - { - name = "nix"; - auto-format = true; - formatter.command = "${pkgs.nixfmt}/bin/nixfmt"; - } - { - name = "rust"; - auto-format = true; - formatter.command = "${pkgs.rustfmt}/bin/rustfmt"; - } - ]; - }; - programs.jujutsu = { - package = unstable.jujutsu; - enable = true; - settings = { - user.name = "Noah Pederson"; - user.email = "noah@packetlost.dev"; - ui = { - diff-formatter = [ - "difft" - "--color" - "always" - "$left" - "$right" - ]; - conflict-marker-style = "git"; - default-command = "log"; - }; - git = { - default-branch = "master"; - }; + nix-index = { + enable = true; + enableFishIntegration = true; }; - }; - programs.git = { - enable = true; - lfs.enable = true; - settings = { - user.name = "Noah Pederson"; - user.email = "noah@packetlost.dev"; - sendemail = { - smtpserver = "smtp.migadu.com"; - smtpuser = "noah@packetlost.dev"; - smtpauth = "plain"; - smtpencryption = "tls"; - smtpserverport = 465; - }; - init = { - defaultBranch = "master"; - # The world isn't ready for sha256 git yet - #defaultObjectFormat = "sha256"; - }; - pull = { - rebase = true; - }; - push = { - default = "simple"; - autoSetupRemote = true; - followTags = true; - }; - credential = { - helper = "cache"; - }; - alias = { - out = "log @{u}.."; - }; - column = { - ui = "auto"; - }; - branch = { - sort = "-committerdate"; - }; - tag = { - sort = "version:refname"; - }; - diff = { - algorithm = "histogram"; - colorMoved = "plain"; - external = "difft"; - mnemonicPrefix = true; - renames = true; - tool = "difftastic"; - }; - difftool = { - prompt = false; - difftastic = { - cmd = ''difft "$LOCAL" "$REMOTE"''; + fzf = { + enable = true; + enableFishIntegration = true; + }; + pistol.enable = true; + neovim = { + package = neovim-unwrapped; + enable = true; + defaultEditor = true; + withRuby = true; + withNodeJs = true; + withPython3 = true; + extraPackages = with pkgs; [ + unstable.fzf + unstable.ripgrep + luarocks + unstable.tree-sitter + ]; + }; + helix = { + enable = true; + settings = { + theme = "everforest_dark"; + editor.cursor-shape = { + normal = "block"; + insert = "bar"; + select = "underline"; }; }; - fetch = { - prune = true; - pruneTags = true; - all = true; - }; - help = { - autocorrect = "prompt"; - }; - commit = { - verbose = true; - }; - rerere = { - enabled = true; - autoupdate = true; - }; - rebase = { - autoSquash = true; - autoStash = true; - updateRefs = true; - }; - merge = { - conflictStyle = "zdiff3"; + languages.language = [ + { + name = "nix"; + auto-format = true; + formatter.command = "${pkgs.nixfmt}/bin/nixfmt"; + } + { + name = "rust"; + auto-format = true; + formatter.command = "${pkgs.rustfmt}/bin/rustfmt"; + } + ]; + }; + jujutsu = { + package = unstable.jujutsu; + enable = true; + settings = { + user.name = "Noah Pederson"; + user.email = "noah@packetlost.dev"; + ui = { + diff-formatter = [ + "difft" + "--color" + "always" + "$left" + "$right" + ]; + conflict-marker-style = "git"; + default-command = "log"; + }; + git = { + default-branch = "master"; + }; }; }; - ignores = [ - ".direnv/" - ".envrc" - ".env/" - ".clj-kondo/" - ]; - }; - programs.aerc = { - enable = true; - }; - programs.yazi = - let - localPkgs = pkgs; - yaziPlugins = localPkgs.yaziPlugins; - plugins = lib.attrsets.getAttrs [ - "rsync" - "piper" - "nord" - "mediainfo" - "glow" - "git" - "diff" - "duckdb" - ] yaziPlugins; - in - { - inherit plugins; + git = { enable = true; - package = localPkgs.yazi; - enableFishIntegration = true; - shellWrapperName = "yy"; + lfs.enable = true; settings = { - preview = { - image_quality = 90; + user.name = "Noah Pederson"; + user.email = "noah@packetlost.dev"; + sendemail = { + smtpserver = "smtp.migadu.com"; + smtpuser = "noah@packetlost.dev"; + smtpauth = "plain"; + smtpencryption = "tls"; + smtpserverport = 465; }; - tasks = { - image_bound = [ - 0 - 0 - ]; + init = { + defaultBranch = "master"; + # The world isn't ready for sha256 git yet + #defaultObjectFormat = "sha256"; + }; + pull = { + rebase = true; + }; + push = { + default = "simple"; + autoSetupRemote = true; + followTags = true; + }; + credential = { + helper = "cache"; + }; + alias = { + out = "log @{u}.."; + }; + column = { + ui = "auto"; + }; + branch = { + sort = "-committerdate"; + }; + tag = { + sort = "version:refname"; + }; + diff = { + algorithm = "histogram"; + colorMoved = "plain"; + external = "difft"; + mnemonicPrefix = true; + renames = true; + tool = "difftastic"; + }; + difftool = { + prompt = false; + difftastic = { + cmd = ''difft "$LOCAL" "$REMOTE"''; + }; + }; + fetch = { + prune = true; + pruneTags = true; + all = true; + }; + help = { + autocorrect = "prompt"; + }; + commit = { + verbose = true; + }; + rerere = { + enabled = true; + autoupdate = true; + }; + rebase = { + autoSquash = true; + autoStash = true; + updateRefs = true; + }; + merge = { + conflictStyle = "zdiff3"; }; }; + ignores = [ + ".direnv/" + ".envrc" + ".env/" + ".clj-kondo/" + ]; }; + aerc = { + enable = true; + }; + yazi = + let + localPkgs = pkgs; + inherit (localPkgs) yaziPlugins; + plugins = lib.attrsets.getAttrs [ + "rsync" + "piper" + "nord" + "mediainfo" + "glow" + "git" + "diff" + "duckdb" + ] yaziPlugins; + in + { + inherit plugins; + enable = true; + package = localPkgs.yazi; + enableFishIntegration = true; + shellWrapperName = "yy"; + settings = { + preview = { + image_quality = 90; + }; + tasks = { + image_bound = [ + 0 + 0 + ]; + }; + }; + }; - # XDG config - xdg.enable = true; - - xdg.configFile.nvim = { - source = ../../nvim; - recursive = true; - }; - xdg.configFile.vis = { - source = ../../vis; - recursive = true; }; - xdg.configFile.fish = { - source = ../../fish; - recursive = true; - force = true; - }; - xdg.configFile."fish/completions/nix.fish".source = - "${pkgs.nix}/share/fish/vendor_completions.d/nix.fish"; - xdg.configFile."fish/completions/zellij.fish".source = - "${unstable.zellij}/share/fish/vendor_completions.d/zellij.fish"; - xdg.configFile.aerc = { - source = ../../aerc; - recursive = true; - }; + # XDG config + xdg = { + enable = true; + configFile = { + nvim = { + source = ../../nvim; + recursive = true; + }; + vis = { + source = ../../vis; + recursive = true; + }; - xdg.configFile.ghostty = { - source = ../../ghostty; - recursive = true; - force = true; + fish = { + source = ../../fish; + recursive = true; + force = true; + }; + "fish/completions/nix.fish".source = "${pkgs.nix}/share/fish/vendor_completions.d/nix.fish"; + "fish/completions/zellij.fish".source = + "${unstable.zellij}/share/fish/vendor_completions.d/zellij.fish"; + aerc = { + source = ../../aerc; + recursive = true; + }; + + ghostty = { + source = ../../ghostty; + recursive = true; + force = true; + }; + opencode = { + source = ../../opencode; + recursive = true; + }; + polytoken = { + source = ../../polytoken; + recursive = true; + }; + }; + dataFile.janet = { + source = ../../janet; + recursive = true; + }; }; home.file.".local/bin" = { source = ../../scripts; recursive = true; }; - xdg.dataFile.janet = { - source = ../../janet; - recursive = true; - }; - - xdg.configFile.opencode = { - source = ../../opencode; - recursive = true; - }; - xdg.configFile.polytoken = { - source = ../../polytoken; - recursive = true; - }; - home.file.".luacheckrc" = { text = '' globals = { diff --git a/modules/nix-remote-builders.nix b/modules/nix-remote-builders.nix index a159b53..3ccce92 100644 --- a/modules/nix-remote-builders.nix +++ b/modules/nix-remote-builders.nix @@ -55,12 +55,9 @@ let ]; in { - nix.distributedBuilds = true; - nix.settings.builders-use-substitutes = true; - programs.ssh.knownHosts = builtins.listToAttrs ( map (builder: { - name = builder.name; + inherit (builder) name; value = { hostNames = [ builder.name @@ -71,11 +68,15 @@ in }) builders ); - nix.buildMachines = map ( - builder: - builtins.removeAttrs builder [ - "name" - "publicKey" - ] - ) (lib.filter (builder: builder.name != config.networking.hostName) builders); + nix = { + distributedBuilds = true; + settings.builders-use-substitutes = true; + buildMachines = map ( + builder: + builtins.removeAttrs builder [ + "name" + "publicKey" + ] + ) (lib.filter (builder: builder.name != config.networking.hostName) builders); + }; } diff --git a/modules/pounce.nix b/modules/pounce.nix index c9176cc..8d64f42 100644 --- a/modules/pounce.nix +++ b/modules/pounce.nix @@ -233,7 +233,7 @@ in users.users = lib.mkIf cfg.createUser { ${cfg.user} = { isSystemUser = true; - group = cfg.group; + inherit (cfg) group; home = cfg.dataDir; }; }; @@ -248,7 +248,7 @@ in { domain = cfg.tls.acme.domain; extraDomainNames = cfg.tls.acme.extraDomainNames; - group = cfg.group; + inherit (cfg) group; reloadServices = serviceNames; } // lib.optionalAttrs (cfg.tls.acme.dnsProvider != null) { diff --git a/modules/secure-env-var.nix b/modules/secure-env-var.nix index 59affe4..0227fff 100644 --- a/modules/secure-env-var.nix +++ b/modules/secure-env-var.nix @@ -35,9 +35,11 @@ in }; config = { - secureEnvVar.files.kagi-env.source = ../secrets/kagi-env.age; - secureEnvVar.files.pushover-env.source = ../secrets/pushover-env.age; - secureEnvVar.files.dev-secrets-env.source = ../secrets/dev-secrets-env.age; + secureEnvVar.files = { + kagi-env.source = ../secrets/kagi-env.age; + pushover-env.source = ../secrets/pushover-env.age; + dev-secrets-env.source = ../secrets/dev-secrets-env.age; + }; age.secrets = lib.mapAttrs (_: envFile: { file = envFile.source; diff --git a/modules/xrdp-lxqt-desktop.nix b/modules/xrdp-lxqt-desktop.nix index 85d40e8..9519f98 100644 --- a/modules/xrdp-lxqt-desktop.nix +++ b/modules/xrdp-lxqt-desktop.nix @@ -30,21 +30,20 @@ in ./xrdp-lxqt-home.nix ]; - services.xserver.desktopManager.lxqt = { - enable = true; + services = { + xserver.desktopManager.lxqt.enable = true; + # xscreensaver can blank or lock xRDP's virtual X display in a way that + # looks like a dead remote desktop session. LXQt is used for remote desktop + # here, so it does not need a system screensaver. + xscreensaver.enable = false; + xrdp = { + enable = true; + openFirewall = true; + defaultWindowManager = toString xrdpLxqtSession; + }; }; - # xscreensaver can blank or lock xRDP's virtual X display in a way that - # looks like a dead remote desktop session. LXQt is used for remote desktop - # here, so it does not need a system screensaver. - services.xscreensaver.enable = false; security.pam.services.xscreensaver.enable = false; - services.xrdp = { - enable = true; - openFirewall = true; - defaultWindowManager = toString xrdpLxqtSession; - }; - programs.dconf.enable = true; xdg.portal.extraPortals = [ diff --git a/overlays/inetutils.nix b/overlays/inetutils.nix index 63f69b7..e443591 100644 --- a/overlays/inetutils.nix +++ b/overlays/inetutils.nix @@ -1,7 +1,7 @@ { pkgs, ... }: { home.packages = [ - (pkgs.inetutils.overrideAttrs (oldAttrs: rec { + (pkgs.inetutils.overrideAttrs (_: rec { version = "2.6"; src = pkgs.fetchurl { url = "mirror://gnu/inetutils/inetutils-${version}.tar.xz"; diff --git a/overlays/nixery.nix b/overlays/nixery.nix index aea00d3..fd7bd8a 100644 --- a/overlays/nixery.nix +++ b/overlays/nixery.nix @@ -22,8 +22,8 @@ in { inherit nixeryPackages; - nixery = nixeryPackages.nixery; - nixery-image = nixeryPackages.nixery-image; - nixery-popcount = nixeryPackages.nixery-popcount; - nixery-prepare-image = nixeryPackages.nixery-prepare-image; + inherit (nixeryPackages) nixery; + inherit (nixeryPackages) nixery-image; + inherit (nixeryPackages) nixery-popcount; + inherit (nixeryPackages) nixery-prepare-image; } diff --git a/services.nix b/services.nix index 2ad4571..38f626d 100644 --- a/services.nix +++ b/services.nix @@ -8,11 +8,13 @@ # Some programs need SUID wrappers, can be configured further or are # started in user sessions. - programs.mtr.enable = true; + programs = { + mtr.enable = true; + fish.enable = true; + mosh.enable = true; + }; # Fish shell, the best - programs.fish.enable = true; - # Tailscale services.tailscale = { enable = true; @@ -31,7 +33,6 @@ }; # MOSH, SSH over flakey connections - programs.mosh.enable = true; } // lib.optionalAttrs enableNFTables { # Use nftables diff --git a/users.nix b/users.nix index ba14dfa..e7d0b5e 100644 --- a/users.nix +++ b/users.nix @@ -10,7 +10,10 @@ # Declarative only optoins. # I don't want to allow ad-hoc modifying users on the system. # Users must be declared either as part of a package or in this file. - users.mutableUsers = false; + users = { + mutableUsers = false; + groups.nas.gid = 1001; + }; age.secrets.noah-password = { file = ./secrets/noah-hashed-password.age; @@ -84,5 +87,4 @@ # ) #); }; - users.groups.nas.gid = 1001; }