diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cde8192..77df51d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,14 +26,14 @@ repos: - id: remove-crlf - id: remove-tabs exclude: (Makefile|Caddyfile) - - repo: https://github.com/zricethezav/gitleaks - rev: v8.22.0 - hooks: - - id: gitleaks - - repo: https://github.com/yuvipanda/pre-commit-hook-ensure-sops - rev: v1.1 - hooks: - - id: sops-encryption - # Uncomment to exclude all markdown files from encryption - # exclude: *.\.md - files: .*secrets.* + # - repo: https://github.com/zricethezav/gitleaks + # rev: v8.23.3 + # hooks: + # - id: gitleaks + # - repo: https://github.com/yuvipanda/pre-commit-hook-ensure-sops + # rev: v1.1 + # hooks: + # - id: sops-encryption + # # Uncomment to exclude all markdown files from encryption + # # exclude: *.\.md + # files: .*secrets.* diff --git a/flake.lock b/flake.lock index 7168bc6..e0cf59c 100644 --- a/flake.lock +++ b/flake.lock @@ -219,24 +219,6 @@ "inputs": { "systems": "systems_2" }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "inputs": { - "systems": "systems_3" - }, "locked": { "lastModified": 1731533236, "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", @@ -251,9 +233,9 @@ "type": "github" } }, - "flake-utils_3": { + "flake-utils_2": { "inputs": { - "systems": "systems_4" + "systems": "systems_3" }, "locked": { "lastModified": 1681202837, @@ -269,9 +251,9 @@ "type": "github" } }, - "flake-utils_4": { + "flake-utils_3": { "inputs": { - "systems": "systems_5" + "systems": "systems_4" }, "locked": { "lastModified": 1710146030, @@ -287,9 +269,9 @@ "type": "github" } }, - "flake-utils_5": { + "flake-utils_4": { "inputs": { - "systems": "systems_6" + "systems": "systems_5" }, "locked": { "lastModified": 1731533236, @@ -305,9 +287,9 @@ "type": "github" } }, - "flake-utils_6": { + "flake-utils_5": { "inputs": { - "systems": "systems_8" + "systems": "systems_7" }, "locked": { "lastModified": 1681202837, @@ -670,27 +652,6 @@ "type": "github" } }, - "krewfile": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1737497949, - "narHash": "sha256-xvwx82Wia73UL9Sow/LBhIJ5O2kw4fxPWwUpZdAE4x0=", - "owner": "brumhard", - "repo": "krewfile", - "rev": "b53aa0d0fa8e18c5c672c8f8fdb9a3bf0a1745a0", - "type": "github" - }, - "original": { - "owner": "brumhard", - "repo": "krewfile", - "type": "github" - } - }, "lix": { "flake": false, "locked": { @@ -707,7 +668,7 @@ }, "lix-module": { "inputs": { - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils", "flakey-profile": "flakey-profile", "lix": "lix", "nixpkgs": [ @@ -835,7 +796,7 @@ "nix-minecraft": { "inputs": { "flake-compat": "flake-compat_3", - "flake-utils": "flake-utils_3", + "flake-utils": "flake-utils_2", "nixpkgs": [ "nixpkgs-unstable" ] @@ -857,7 +818,7 @@ "nix-vscode-extensions": { "inputs": { "flake-compat": "flake-compat_4", - "flake-utils": "flake-utils_4", + "flake-utils": "flake-utils_3", "nixpkgs": [ "nixpkgs" ] @@ -1087,7 +1048,7 @@ "nvf": { "inputs": { "flake-parts": "flake-parts_2", - "flake-utils": "flake-utils_5", + "flake-utils": "flake-utils_4", "mnw": "mnw", "nil": "nil", "nixpkgs": "nixpkgs_4", @@ -1258,7 +1219,7 @@ "plugin-vim-startify": "plugin-vim-startify", "plugin-which-key": "plugin-which-key", "plugin-yanky-nvim": "plugin-yanky-nvim", - "systems": "systems_7" + "systems": "systems_6" }, "locked": { "lastModified": 1737955438, @@ -4046,7 +4007,6 @@ "home-manager": "home-manager", "hyprland": "hyprland", "hyprland-plugins": "hyprland-plugins", - "krewfile": "krewfile", "lix-module": "lix-module", "nix-inspect": "nix-inspect", "nix-minecraft": "nix-minecraft", @@ -4255,21 +4215,6 @@ "type": "github" } }, - "systems_8": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "talhelper": { "inputs": { "flake-parts": "flake-parts_3", @@ -4336,7 +4281,7 @@ }, "vscode-server": { "inputs": { - "flake-utils": "flake-utils_6", + "flake-utils": "flake-utils_5", "nixpkgs": "nixpkgs_5" }, "locked": { diff --git a/flake.nix b/flake.nix index 92e1e5e..3542e1e 100644 --- a/flake.nix +++ b/flake.nix @@ -72,11 +72,10 @@ vscode-server.url = "github:nix-community/nixos-vscode-server"; # krewfile - Declarative krew plugin management - krewfile = { - # url = "github:brumhard/krewfile"; - url = "github:brumhard/krewfile"; - inputs.nixpkgs.follows = "nixpkgs"; - }; + # krewfile = { + # url = "github:brumhard/krewfile"; + # inputs.nixpkgs.follows = "nixpkgs"; + # }; # nix-minecraft - Minecraft server management # https://github.com/infinidoge/nix-minecraft @@ -103,12 +102,9 @@ nixpkgs-unstable, sops-nix, home-manager, - nix-vscode-extensions, disko, - talhelper, lix-module, vscode-server, - krewfile, nvf, ... } @ inputs: let @@ -155,6 +151,7 @@ ./nixos/modules/nixos # all machines get nixos modules ./nixos/hosts/${hostname} # load this host's config folder for machine-specific config { + inherit disabledModules; home-manager = { useUserPackages = true; useGlobalPkgs = true; @@ -162,7 +159,6 @@ inherit inputs hostname system; }; }; - disabledModules = disabledModules; } ], profileModules ? [], @@ -201,7 +197,7 @@ "${nixpkgs-unstable}/nixos/modules/services/web-servers/caddy/default.nix" ./nixos/profiles/role-dev.nix ./nixos/profiles/role-server.nix - {home-manager.users.jahanson = ./nixos/home/jahanson/server.nix;} + {home-manager.users.jahanson = ./nixos/home/jahanson/sworkstation.nix;} ]; }; diff --git a/nixos/home/jahanson/sworkstation.nix b/nixos/home/jahanson/sworkstation.nix new file mode 100644 index 0000000..780f54b --- /dev/null +++ b/nixos/home/jahanson/sworkstation.nix @@ -0,0 +1,33 @@ +{pkgs, ...}: { + imports = [ + ./global.nix + ]; + + config = { + myHome = { + programs.firefox.enable = true; + programs.thunderbird.enable = true; + shell = { + # soon(tm) + # ghostty.enable = true; + + git = { + enable = true; + username = "Joseph Hanson"; + email = "joe@veri.dev"; + signingKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIDSAmssproxG+KsVn2DfuteBAemHrmmAFzCtldpKl4J"; + }; + }; + }; + + home = { + # Install these packages for my user + packages = with pkgs; [ + # apps + solaar # open source manager for logitech unifying receivers + # unstable.vesktop # gpu issues. Using the flatpak version solves this issue. + vlc + ]; + }; + }; +} diff --git a/nixos/home/modules/programs/browsers/firefox/default.nix b/nixos/home/modules/programs/browsers/firefox/default.nix index 0d38124..eaad93a 100644 --- a/nixos/home/modules/programs/browsers/firefox/default.nix +++ b/nixos/home/modules/programs/browsers/firefox/default.nix @@ -4,11 +4,9 @@ pkgs, ... }: -with lib; -let +with lib; let cfg = config.myHome.programs.firefox; -in -{ +in { options.myHome.programs.firefox.enable = mkEnableOption "Firefox"; config = mkIf cfg.enable { @@ -18,18 +16,10 @@ in extraPolicies = { DontCheckDefaultBrowser = true; DisablePocket = true; - # See nixpkgs' firefox/wrapper.nix to check which options you can use - nativeMessagingHosts = [ - # Gnome shell native connector - pkgs.gnome-browser-connector - # plasma connector - # plasma5Packages.plasma-browser-integration - ]; }; }; policies = import ./policies.nix; - - profiles.default = import ./profile-default.nix { inherit pkgs; }; + profiles.default = import ./profile-default.nix {inherit pkgs;}; }; }; } diff --git a/nixos/home/modules/programs/browsers/firefox/policies.nix b/nixos/home/modules/programs/browsers/firefox/policies.nix index 5af443b..5c32e6c 100644 --- a/nixos/home/modules/programs/browsers/firefox/policies.nix +++ b/nixos/home/modules/programs/browsers/firefox/policies.nix @@ -8,9 +8,9 @@ Fingerprinting = true; }; DisablePocket = true; - # DisableFirefoxAccounts = true; - # DisableAccounts = true; - # DisableFirefoxScreenshots = true; + DisableFirefoxAccounts = true; + DisableAccounts = true; + DisableFirefoxScreenshots = true; # OverrideFirstRunPage = ""; OverridePostUpdatePage = ""; DontCheckDefaultBrowser = true; diff --git a/nixos/home/modules/programs/browsers/firefox/profile-default.nix b/nixos/home/modules/programs/browsers/firefox/profile-default.nix index a0358be..6e80dca 100644 --- a/nixos/home/modules/programs/browsers/firefox/profile-default.nix +++ b/nixos/home/modules/programs/browsers/firefox/profile-default.nix @@ -1,5 +1,4 @@ -{ pkgs }: -{ +{pkgs}: { id = 0; name = "default"; isDefault = true; @@ -11,22 +10,21 @@ # 2 => the last page viewed in Firefox # 3 => previous session windows and tabs "browser.startup.page" = "3"; - "browser.send_pings" = false; - # Do not track - "privacy.donottrackheader.enabled" = "true"; - "privacy.donottrackheader.value" = 1; "browser.display.use_system_colors" = "true"; - "browser.display.use_document_colors" = "false"; "devtools.theme" = "dark"; - "extensions.pocket.enabled" = false; }; extensions = with pkgs.nur.repos.rycee.firefox-addons; [ ublock-origin privacy-badger - link-cleaner refined-github + kagi-search + languagetool + onepassword-password-manager + streetpass-for-mastodon + dearrow + sponsorblock ]; } diff --git a/nixos/hosts/shadowfax/config/sops-secrets.nix b/nixos/hosts/shadowfax/config/sops-secrets.nix new file mode 100644 index 0000000..f2348ec --- /dev/null +++ b/nixos/hosts/shadowfax/config/sops-secrets.nix @@ -0,0 +1,107 @@ +{ ... }: +{ + secrets = { + # Minio + "minio" = { + sopsFile = ../secrets.sops.yaml; + owner = "minio"; + group = "minio"; + mode = "400"; + restartUnits = [ "minio.service" ]; + }; + # Syncthing + "syncthing/publicCert" = { + sopsFile = ../secrets.sops.yaml; + owner = "jahanson"; + mode = "400"; + restartUnits = [ "syncthing.service" ]; + }; + "syncthing/privateKey" = { + sopsFile = ../secrets.sops.yaml; + owner = "jahanson"; + mode = "400"; + restartUnits = [ "syncthing.service" ]; + }; + # Prowlarr + "arr/prowlarr/apiKey" = { + sopsFile = ../secrets.sops.yaml; + owner = "prowlarr"; + mode = "400"; + restartUnits = [ "prowlarr.service" ]; + }; + "arr/prowlarr/postgres/dbName" = { + sopsFile = ../secrets.sops.yaml; + owner = "prowlarr"; + mode = "400"; + restartUnits = [ "prowlarr.service" ]; + }; + "arr/prowlarr/postgres/user" = { + sopsFile = ../secrets.sops.yaml; + owner = "prowlarr"; + mode = "400"; + restartUnits = [ "prowlarr.service" ]; + }; + "arr/prowlarr/postgres/password" = { + sopsFile = ../secrets.sops.yaml; + owner = "prowlarr"; + mode = "400"; + restartUnits = [ "prowlarr.service" ]; + }; + "arr/prowlarr/postgres/host" = { + sopsFile = ../secrets.sops.yaml; + owner = "prowlarr"; + mode = "400"; + restartUnits = [ "prowlarr.service" ]; + }; + # # Sonarr + # "arr/sonarr/apiKey" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "sonarr"; + # mode = "400"; + # restartUnits = [ "sonarr.service" ]; + # }; + # "arr/sonarr/postgres/dbName" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "sonarr"; + # mode = "400"; + # restartUnits = [ "sonarr.service" ]; + # }; + # "arr/sonarr/postgres/user" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "sonarr"; + # mode = "400"; + # restartUnits = [ "sonarr.service" ]; + # }; + # "arr/sonarr/postgres/password" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "sonarr"; + # mode = "400"; + # restartUnits = [ "sonarr.service" ]; + # }; + # # Radarr + # "arr/radarr/apiKey" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "radarr"; + # mode = "400"; + # restartUnits = [ "radarr.service" ]; + # }; + # "arr/radarr/postgres/dbName" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "radarr"; + # mode = "400"; + # restartUnits = [ "radarr.service" ]; + # }; + # "arr/radarr/postgres/user" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "radarr"; + # mode = "400"; + # restartUnits = [ "radarr.service" ]; + # }; + # "arr/radarr/postgres/password" = { + # sopsFile = ../secrets.sops.yaml; + # owner = "radarr"; + # mode = "400"; + # restartUnits = [ "radarr.service" ]; + # }; + }; +} diff --git a/nixos/hosts/shadowfax/default.nix b/nixos/hosts/shadowfax/default.nix index c6c8902..793482a 100644 --- a/nixos/hosts/shadowfax/default.nix +++ b/nixos/hosts/shadowfax/default.nix @@ -4,26 +4,28 @@ inputs, pkgs, ... -}: let - sanoidConfig = import ./config/sanoid.nix {}; +}: +let + sanoidConfig = import ./config/sanoid.nix { }; disks = import ./config/disks.nix; - smartdDevices = map (device: {inherit device;}) disks; -in { + smartdDevices = map (device: { inherit device; }) disks; +in +{ imports = [ inputs.disko.nixosModules.disko (import ../../profiles/disko-nixos.nix { - disks = ["/dev/sda|/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_500GB_S58SNM0W406409E"]; + disks = [ "/dev/sda|/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_500GB_S58SNM0W406409E" ]; }) inputs.nix-minecraft.nixosModules.minecraft-servers ]; boot = { initrd = { - kernelModules = ["nfs"]; - supportedFilesystems = ["nfs"]; + kernelModules = [ "nfs" ]; + supportedFilesystems = [ "nfs" ]; }; - binfmt.emulatedSystems = ["aarch64-linux"]; # Enabled for arm compilation + binfmt.emulatedSystems = [ "aarch64-linux" ]; # Enabled for arm compilation kernelModules = [ "vfio" @@ -31,11 +33,11 @@ in { "vfio_pci" "vfio_virqfd" ]; - extraModulePackages = []; - kernelParams = ["zfs.zfs_arc_max=107374182400"]; # 100GB + extraModulePackages = [ ]; + kernelParams = [ "zfs.zfs_arc_max=107374182400" ]; # 100GB }; - swapDevices = []; + swapDevices = [ ]; hardware = { cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; @@ -45,8 +47,7 @@ in { nvidia-container-toolkit.enable = true; }; - users.users.root.openssh.authorizedKeys.keys = []; - + users.users.root.openssh.authorizedKeys.keys = [ ]; # Network settings networking = { hostName = "shadowfax"; @@ -134,7 +135,7 @@ in { # Minio minio = { enable = true; - dataDir = ["/eru/minio"]; + dataDir = [ "/eru/minio" ]; rootCredentialsFile = config.sops.secrets."minio".path; }; @@ -161,7 +162,7 @@ in { # Soft Serve - SSH git server soft-serve = { enable = true; - settings = import ./config/soft-serve.nix {}; + settings = import ./config/soft-serve.nix { }; }; sunshine = { @@ -181,7 +182,7 @@ in { # VSCode Compatibility Settings vscode-server.enable = true; - xserver.videoDrivers = ["nvidia"]; + xserver.videoDrivers = [ "nvidia" ]; greetd = { enable = true; vt = 3; @@ -195,27 +196,7 @@ in { }; # sops - sops.secrets = { - "minio" = { - sopsFile = ./secrets.sops.yaml; - owner = "minio"; - group = "minio"; - mode = "400"; - restartUnits = ["minio.service"]; - }; - "syncthing/publicCert" = { - sopsFile = ./secrets.sops.yaml; - owner = "jahanson"; - mode = "400"; - restartUnits = ["syncthing.service"]; - }; - "syncthing/privateKey" = { - sopsFile = ./secrets.sops.yaml; - owner = "jahanson"; - mode = "400"; - restartUnits = ["syncthing.service"]; - }; - }; + sops = import ./config/sops-secrets.nix { }; # System settings and services. mySystem = { @@ -239,9 +220,17 @@ in { enable = true; package = pkgs.unstable.prowlarr; dataDir = "/nahar/prowlarr"; - hardening = true; - openFirewall = true; port = 9696; + openFirewall = true; + hardening = true; + apiKeyFile = config.sops.secrets."arr/prowlarr/apiKey".path; + db = { + enable = true; + hostFile = config.sops.secrets."arr/prowlarr/postgres/host".path; + port = 5432; + userFile = config.sops.secrets."arr/prowlarr/postgres/user".path; + passwordFile = config.sops.secrets."arr/prowlarr/postgres/password".path; + }; }; # Sabnzbd sabnzbd = { @@ -281,7 +270,7 @@ in { # qBittorrent qbittorrent = { enable = true; - package = pkgs.unstable.qbittorrent.override {guiSupport = false;}; + package = pkgs.unstable.qbittorrent.override { guiSupport = false; }; dataDir = "/nahar/qbittorrent"; downloadsDir = "/eru/media/qb/downloads"; webuiPort = 8456; @@ -302,9 +291,9 @@ in { system = { incus = { enable = true; - preseed = import ./config/incus-preseed.nix {}; + preseed = import ./config/incus-preseed.nix { }; }; - motd.networkInterfaces = ["bond0"]; + motd.networkInterfaces = [ "bond0" ]; nfs.enable = true; zfs.enable = true; zfs.mountPoolsAtBoot = [ diff --git a/nixos/hosts/shadowfax/secrets.sops.yaml b/nixos/hosts/shadowfax/secrets.sops.yaml index 39069cb..56dc9e1 100644 --- a/nixos/hosts/shadowfax/secrets.sops.yaml +++ b/nixos/hosts/shadowfax/secrets.sops.yaml @@ -6,6 +6,29 @@ restic: resticUri: ENC[AES256_GCM,data:aA3kc/Wxg/UxrAUeDd0y9z/8mN9LjWsycS3aUuEwgTcAO2NkfUcH9kw/PXOvazA8t5UJ9RVPYYF7910JeftmMNgs,iv:4GaR5XuJKPnQsBehihraCgqBUumDeq6IiRQrSvtQKgg=,tag:U1fVporyT4S48Dmdf5ghSw==,type:str] resticPassword: ENC[AES256_GCM,data:rC5P60IK52dYOSiSkpnkZ2VvqI0=,iv:xIr6BYmpbGXg9zKCKVcstK2ANHN2Y0MzZ1HhDIL9oxI=,tag:J14I0dvIW0FMW1LLB4KuNw==,type:str] minio: ENC[AES256_GCM,data:IJTwUJOC84a5n798fTDlwRzVc8p5zRiccjdoNTPCNlls0RAyGllijf7GAQG3fxQZQWB2xNd7G0F4/Bv+KmThX2Nxy0c5JFbed+AekuMbNQ==,iv:QDB8JUSehsApBnRhLeGtS2ZczIJA0awN0g0sfkKK810=,tag:NMDfAN8R0mcT7Ec1ldyZbw==,type:str] +postgres: + host: ENC[AES256_GCM,data:fd0SCRhtJWA=,iv:KNSZ2iaCum+0AlDlgrH5VAVj7D1RRJSSFGEw0eYi5+4=,tag:Gs5HHPN9SeDm+CIzD7GPXQ==,type:str] + port: ENC[AES256_GCM,data:Z0fHNA==,iv:otbEsYxhJ6/YR+A5oRx3Dwrqk6T6BL9OGka5yu1H+HA=,tag:T+KW8DaRJ8NN7k1mIMn6QA==,type:int] +arr: + prowlarr: + apiKey: ENC[AES256_GCM,data:qxm2yp8ReuMgQ0155mKBAWickKusOaa/FeoIopj9l1Z3,iv:pAeDxK6CGap4fKU5xQ5hZR9It6/1uo27dKZBi5Bl3rc=,tag:HZl914AfFU4D5J7cDS3I1g==,type:str] + postgres: + host: ENC[AES256_GCM,data:gvGJT0521ZE=,iv:JsYsq8iQjpU+4eGwbUUx85Vx5ZS7UwVLJpR2K0bUwv8=,tag:xALURbOgT3Xl2x2kXaLE/Q==,type:str] + dbName: ENC[AES256_GCM,data:2EFvYnz9swxo9nSggQ==,iv:k24q941nEF//Yojv15s4HNiA/V5/G7I0BhWskScv1uA=,tag:BN9thh3VaxFyhq7m5S0dqQ==,type:str] + user: ENC[AES256_GCM,data:gO8c5bZ3oDY=,iv:YggC8TNFzqHRcRxSBDiV580xF3kLQKgR/ScfyW+5Y5A=,tag:bY7QduxooRkR5SFBxlKjxQ==,type:str] + password: ENC[AES256_GCM,data:rqryseQj0lMiNmB21ezXYQ7ceaOtiZJLPA==,iv:f0ahBkII+pZOPB50EcCIEMbvHriYHv7ax/u1515KAA8=,tag:EObTc1yd/GTNuVE87tPg0g==,type:str] + sonarr: + apiKey: ENC[AES256_GCM,data:TVy4L0ctHhT3gNp+WCaLCUVc0no8VIkWenroFOYk8h4z,iv:A0a6IUBeDDxPiLlrPCXhXu586QRnXha0RthuXUKkU4I=,tag:oVMS5Ys/NiDrA6YSiCjqsw==,type:str] + postgres: + dbName: ENC[AES256_GCM,data:Um9YpALoU7qQfTo=,iv:q0IVjaxyaG8MWAxp43kZjHIBm6dWv37maykSfhAxe1M=,tag:NLqIikfWculCeuoRqPHc8Q==,type:str] + user: ENC[AES256_GCM,data:Vd68IvZs,iv:DYT3PudE94JZZTZHzV8QgRYADtThZhxTjFJByLcZP1c=,tag:pX1ZNC+M9Jm+PlQ22BZMRw==,type:str] + password: ENC[AES256_GCM,data:XOrycMom2utnefraGPoAq7xtP6yfSzTb8g==,iv:WQInK+bJuDNI9uN/GeQ2Fb1Mmlux6+lXwkGS1ZEh+kQ=,tag:DGqLerxomCVfVv15Gt3b8A==,type:str] + radarr: + apiKey: ENC[AES256_GCM,data:Qcfzr12aftnS+b3pDHHnfOya1+vlyVaoNCPLzJ9xv5Pv,iv:9M33sfqZPzeghxmBtYk3LgsfbInC7sPSQGuYFJiydh4=,tag:lSmi6Do64sarG15q6+yuQw==,type:str] + postgres: + dbName: ENC[AES256_GCM,data:zC4j0VJJpWWT0XY=,iv:ITupnWLgvI2wAPnkD826S77BMELDqRWZKax51SVkBgA=,tag:L7YXfoxAhi94ssBoE35Aug==,type:str] + user: ENC[AES256_GCM,data:jaYUWAzQ,iv:ayEutHFPyZ7CN3inTqmgPmintR8qE8HfatvzCx7VXnA=,tag:3Ou0JRzpcihL0AWcC0pC5w==,type:str] + password: ENC[AES256_GCM,data:XcS9H5L+ikA2KflepKrBHVlBjKwB0Vu8mw==,iv:lSpoEiCqOpP3p1T7bBH8F9YiSf2kwQQC+FQPuaKojnE=,tag:ScV/E6JeomQlfp35NIrh1g==,type:str] sops: kms: [] gcp_kms: [] @@ -84,8 +107,8 @@ sops: aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-01-23T00:36:34Z" - mac: ENC[AES256_GCM,data:2H1NCCVjvR/pSTI6njNkE7RuWWlCSPIvKLBqkJbEKNvc2aaPIUmGLlLpvNRQ1rQJbQa2okVnL4wITeYT+uuBhus4ubTAD7RH3HIjXMcK2HFCA/ey/kJ9GZI6I+0pwyjavUlWitIqUjUpTOK1hGSTzRSm6G38uSLhfQGMG3clUjw=,iv:1qZ6eKIaE/6QF3r4adGw2dvKlrZvjCktmgJ2L3n3kEs=,tag:kZ7wAbXebk0VF1kAbjxRSA==,type:str] + lastmodified: "2025-02-01T19:17:22Z" + mac: ENC[AES256_GCM,data:yUnivIIT8LKsq+Ymc2SiI0ei1jaaESwvyNX77U2zTf70mPplzMQmRIvV10x5mxZ0RTfxQzyudpCZV1cchFxmi7Nwz/YUVcxffd8ohN5vRQDM73ONODxcVnFxBuJh9n2Hnf1jOWxOGo39p235SvxlQHl5jai+sezUN8dBqIgEzts=,iv:XC8Ra3vuNQIdbxUlLoXlCIkqANtkybuyYaS4M9hKcS8=,tag:WWPe8oFlKtsL/pA0Epo0kQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.9.2 + version: 3.9.3 diff --git a/nixos/modules/nixos/editor/nvim.nix b/nixos/modules/nixos/editor/nvim.nix index 01ec950..eb27f68 100644 --- a/nixos/modules/nixos/editor/nvim.nix +++ b/nixos/modules/nixos/editor/nvim.nix @@ -12,6 +12,14 @@ in { programs.nvf = { enable = true; settings.vim = { + keymaps = [ + { + mode = "n"; + key = "rp"; + action = ":lua require('precognition').peek()"; + desc = "Peek recognition"; + } + ]; viAlias = false; vimAlias = true; lsp = { @@ -127,7 +135,10 @@ in { motion = { hop.enable = true; leap.enable = true; - precognition.enable = false; + precognition = { + enable = true; + setupOpts.startVisible = false; + }; }; images = { image-nvim.enable = false; diff --git a/nixos/modules/nixos/editor/vscode.nix b/nixos/modules/nixos/editor/vscode.nix index fffa971..f4aa558 100644 --- a/nixos/modules/nixos/editor/vscode.nix +++ b/nixos/modules/nixos/editor/vscode.nix @@ -14,11 +14,9 @@ with lib; let "editorconfig.editorconfig" "esbenp.prettier-vscode" "foxundermoon.shell-format" - # "github.copilot" "jnoortheen.nix-ide" "mikestead.dotenv" "mrmlnc.vscode-json5" - # "ms-python.python" # Python extensions *required* for redhat.ansible/vscode-yaml "ms-python.vscode-pylance" "ms-vscode-remote.remote-ssh-edit" "pkief.material-icon-theme" @@ -33,7 +31,9 @@ with lib; let "rust-lang.rust-analyzer" "dustypomerleau.rust-syntax" "exiasr.hadolint" + # "github.copilot" # "github.copilot-chat" + # "ms-python.python" # Python extensions *required* for redhat.ansible/vscode-yaml ]; # Nixpkgs Extensions. These are updated whenver they get around to it. vscodeNixpkgsExtensions = [ diff --git a/nixos/modules/nixos/services/prowlarr/default.nix b/nixos/modules/nixos/services/prowlarr/default.nix new file mode 100644 index 0000000..6e72a73 --- /dev/null +++ b/nixos/modules/nixos/services/prowlarr/default.nix @@ -0,0 +1,270 @@ +{ + config, + pkgs, + lib, + utils, + ... +}: +with lib; let + cfg = config.mySystem.services.prowlarr; + dbOptions = { + options = { + enable = mkEnableOption "Database configuration for Prowlarr"; + host = mkOption { + type = types.str; + default = ""; + example = "127.0.0.1"; + description = "Direct database host (mutually exclusive with hostFile)"; + }; + hostFile = mkOption { + type = types.str; + default = ""; + example = "/run/secrets/prowlarr_db_host"; + description = "Database host from a file (mutually exclusive with host)"; + }; + port = mkOption { + type = types.port; + default = "5432"; + description = "Database port"; + }; + user = mkOption { + type = types.str; + default = "prowlarr"; + description = "Direct database user (mutually exclusive with userFile)"; + }; + userFile = mkOption { + type = types.str; + default = ""; + example = "/run/secrets/prowlarr_db_user"; + description = "Database user from a file (mutually exclusive with user)"; + }; + passwordFile = mkOption { + type = types.path; + default = "/run/secrets/prowlarr_db_password"; + description = "Database password from a file (always used)"; + }; + dbname = mkOption { + type = types.str; + default = "prowlarr_main"; + description = "Database name"; + }; + }; + }; +in { + options.mySystem.services.prowlarr = { + enable = mkEnableOption "Prowlarr"; + + package = mkPackageOption pkgs "prowlarr" {}; + + user = mkOption { + type = types.str; + default = "prowlarr"; + description = "User account under which Prowlarr runs."; + }; + + group = mkOption { + type = types.str; + default = "prowlarr"; + description = "Group under which Prowlarr runs."; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/prowlarr"; + description = "Storage directory for Prowlarr data"; + }; + + port = mkOption { + type = types.port; + default = 9696; + description = "Port for Prowlarr web interface"; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = "Open firewall ports for Prowlarr"; + }; + + hardening = mkOption { + type = types.bool; + default = true; + description = "Enable security hardening features"; + }; + + apiKey = mkOption { + type = types.str; + default = ""; + example = "abc123"; + description = "Direct API key for Prowlarr (mutually exclusive with apiKeyFile)"; + }; + + apiKeyFile = mkOption { + type = types.path; + default = "/run/secrets/prowlarr_api_key"; + description = "API key for Prowlarr from a file (mutually exclusive with apiKey)"; + }; + + db = mkOption { + type = types.submodule dbOptions; + example = { + enable = true; + host = "10.5.0.5"; # or use hostFile + port = "5432"; + user = "prowlarr"; # or userFile + passwordFile = "/run/secrets/prowlarr_db_password"; + dbname = "prowlarr_main"; + }; + description = "Database settings for Prowlarr."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = !(cfg.db.host != "" && cfg.db.hostFile != ""); + message = "Specify either a direct database host via db.host or a file via db.hostFile (leave direct host empty)."; + } + { + assertion = !(cfg.db.user != "prowlarr" && cfg.db.userFile != ""); + message = "Specify either a direct database user via db.user or a file via db.userFile."; + } + { + assertion = !(cfg.apiKey != "" && cfg.apiKeyFile != ""); + message = "Specify either a direct API key via apiKey or a file via apiKeyFile (leave direct API key empty)."; + } + ]; + + systemd.services.prowlarr = { + description = "Prowlarr"; + after = [ + "network.target" + "nss-lookup.target" + ]; + wantedBy = ["multi-user.target"]; + environment = lib.mkMerge [ + { + PROWLARR__APP__INSTANCENAME = "Prowlarr"; + PROWLARR__APP__THEME = "dark"; + PROWLARR__AUTH__METHOD = "External"; + PROWLARR__AUTH__REQUIRED = "DisabledForLocalAddresses"; + PROWLARR__LOG__DBENABLED = "False"; + PROWLARR__LOG__LEVEL = "info"; + PROWLARR__SERVER__PORT = toString cfg.port; + PROWLARR__UPDATE__BRANCH = "develop"; + } + (lib.mkIf cfg.db.enable { + PROWLARR__POSTGRES__PORT = toString cfg.db.port; + PROWLARR__POSTGRES__MAINDB = cfg.db.dbname; + }) + ]; + + serviceConfig = lib.mkMerge [ + { + Type = "simple"; + User = cfg.user; + Group = cfg.group; + ExecStart = utils.escapeSystemdExecArgs [ + (lib.getExe cfg.package) + "-nobrowser" + "-data=${cfg.dataDir}" + "-port=${toString cfg.port}" + ]; + WorkingDirectory = cfg.dataDir; + RuntimeDirectory = "prowlarr"; + LogsDirectory = "prowlarr"; + RuntimeDirectoryMode = "0750"; + Restart = "on-failure"; + RestartSec = 5; + } + (lib.mkIf cfg.hardening { + CapabilityBoundingSet = [""]; + DeviceAllow = [""]; + DevicePolicy = "closed"; + LockPersonality = true; + # Needs access to .Net CLR memory space. + MemoryDenyWriteExecute = false; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProtectControlGroups = true; + ProtectHome = "read-only"; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + ReadWritePaths = [ + cfg.dataDir + "/var/log/prowlarr" + ]; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_NETLINK" + ]; + RestrictNamespaces = [ + "uts" + "ipc" + "pid" + "user" + "cgroup" + "net" + ]; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + # .Net CLR requirement + #"~@resources" + ]; + }) + (lib.mkIf cfg.db.enable { + ExecStartPre = "+${pkgs.writeShellScript "prowlarr-pre-script" '' + mkdir -p /run/prowlarr + rm -f /run/prowlarr/secrets.env + + # Helper function to safely write variables + write_var() { + local var_name="$1" + local value="$2" + if [ -n "$value" ]; then + printf "%s=%s\n" "$var_name" "$value" >> /run/prowlarr/secrets.env + fi + } + + # API Key (direct value or file) + if [ -n "${cfg.apiKey}" ]; then + write_var "PROWLARR__AUTH__APIKEY" "${cfg.apiKey}" + else + write_var "PROWLARR__AUTH__APIKEY" "$(cat ${cfg.apiKeyFile})" + fi + + # Database Configuration + write_var "PROWLARR__POSTGRES__HOST" "$([ -n "${cfg.db.host}" ] && echo "${cfg.db.host}" || cat "${cfg.db.hostFile}")" + write_var "PROWLARR__POSTGRES__USER" "$([ -n "${cfg.db.user}" ] && echo "${cfg.db.user}" || cat "${cfg.db.userFile}")" + write_var "PROWLARR__POSTGRES__PASSWORD" "$(cat ${cfg.db.passwordFile})" + + # Final permissions + chmod 600 /run/prowlarr/secrets.env + chown ${cfg.user}:${cfg.group} /run/prowlarr/secrets.env + ''}"; + + EnvironmentFile = ["-/run/prowlarr/secrets.env"]; + }) + ]; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [cfg.port]; + }; + + users.groups.${cfg.group} = {}; + users.users = mkIf (cfg.user == "prowlarr") { + prowlarr = { + inherit (cfg) group; + isSystemUser = true; + home = cfg.dataDir; + }; + }; + }; +} diff --git a/nixos/overlays/arr/default.nix b/nixos/overlays/arr/default.nix new file mode 100644 index 0000000..b29c865 --- /dev/null +++ b/nixos/overlays/arr/default.nix @@ -0,0 +1,4 @@ +{pkgs}: let + getPackages = dir: pkgs.lib.mapAttrs (name: _: pkgs.callPackage (dir + "/${name}") {}) (builtins.readDir dir); +in + getPackages ./. diff --git a/nixos/overlays/arr/radarr.nix b/nixos/overlays/arr/radarr.nix new file mode 100644 index 0000000..15a4963 --- /dev/null +++ b/nixos/overlays/arr/radarr.nix @@ -0,0 +1,79 @@ +{ + lib, + stdenv, + fetchurl, + mono, + libmediainfo, + sqlite, + curl, + makeWrapper, + icu, + dotnet-runtime, + openssl, + nixosTests, + zlib, +}: let + os = + if stdenv.hostPlatform.isDarwin + then "osx" + else "linux"; + arch = + { + x86_64-linux = "x64"; + aarch64-linux = "arm64"; + x86_64-darwin = "x64"; + aarch64-darwin = "arm64"; + } + ."${stdenv.hostPlatform.system}" + or (throw "Unsupported system: ${stdenv.hostPlatform.system}"); + + hash = + { + x64-linux_hash = "sha256-08jQhaPPS4zEQuJ2ovP/ZsNXG1dJvia4X6RrXywHNao="; + arm64-linux_hash = "sha256-70IWCu48jvoTHo8Q/78n/ZDmhFwm9PZOYXUl/17insg="; + x64-osx_hash = "sha256-fJAjGx5l4wa27krZFAeKvrWDk9p02HtXhbDv04x0+sA="; + arm64-osx_hash = "sha256-GmWDseb8MrpKIL50KAbTFjzu1MoEZXpzUI44Xwaeoeo="; + } + ."${arch}-${os}_hash"; +in + stdenv.mkDerivation rec { + pname = "radarr"; + version = "5.17.2.9580"; + + src = fetchurl { + url = "https://github.com/Radarr/Radarr/releases/download/v${version}/Radarr.master.${version}.${os}-core-${arch}.tar.gz"; + sha256 = hash; + }; + + nativeBuildInputs = [makeWrapper]; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{bin,share/${pname}-${version}} + cp -r * $out/share/${pname}-${version}/. + + makeWrapper "${dotnet-runtime}/bin/dotnet" $out/bin/Radarr \ + --add-flags "$out/share/${pname}-${version}/Radarr.dll" \ + --prefix LD_LIBRARY_PATH : ${ + lib.makeLibraryPath [ + curl + sqlite + libmediainfo + mono + openssl + icu + zlib + ] + } + + runHook postInstall + ''; + + passthru = { + updateScript = ./update.sh; + tests.smoke-test = nixosTests.radarr; + }; + + mainProgram = "Radarr"; + } diff --git a/nixos/overlays/arr/sonarr.nix b/nixos/overlays/arr/sonarr.nix new file mode 100644 index 0000000..b6aba8a --- /dev/null +++ b/nixos/overlays/arr/sonarr.nix @@ -0,0 +1,77 @@ +{ + lib, + stdenv, + fetchurl, + mono, + libmediainfo, + sqlite, + curl, + makeWrapper, + icu, + dotnet-runtime, + openssl, + nixosTests, + zlib, +}: let + os = + if stdenv.hostPlatform.isDarwin + then "osx" + else "linux"; + arch = + { + x86_64-linux = "x64"; + aarch64-linux = "arm64"; + x86_64-darwin = "x64"; + aarch64-darwin = "arm64"; + } + ."${stdenv.hostPlatform.system}" + or (throw "Unsupported system: ${stdenv.hostPlatform.system}"); + + hash = + { + x64-linux_hash = "sha256-/vsU0M8jyyfYVpE75gSa7R6aSyhxBg8gO3c+G3qCA+E="; + arm64-linux_hash = lib.fakeSha256; + x64-osx_hash = lib.fakeSha256; + arm64-osx_hash = lib.fakeSha256; + } + ."${arch}-${os}_hash"; +in + stdenv.mkDerivation rec { + pname = "sonarr"; + version = "4.0.12.2823"; + + src = fetchurl { + url = "https://github.com/Sonarr/Sonarr/releases/download/v${version}/Sonarr.main.${version}.${os}-${arch}.tar.gz"; + sha256 = hash; + }; + + nativeBuildInputs = [makeWrapper]; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{bin,share/${pname}-${version}} + cp -r * $out/share/${pname}-${version}/. + + makeWrapper "${dotnet-runtime}/bin/dotnet" $out/bin/Sonarr \ + --add-flags "$out/share/${pname}-${version}/Sonarr.dll" \ + --prefix LD_LIBRARY_PATH : ${ + lib.makeLibraryPath [ + curl + sqlite + libmediainfo + mono + openssl + icu + zlib + ] + } + + runHook postInstall + ''; + passthru = { + tests.smoke-test = nixosTests.radarr; + }; + + mainProgram = "Sonarr"; + } diff --git a/nixos/profiles/role-dev.nix b/nixos/profiles/role-dev.nix index e59caac..c3a1f4d 100644 --- a/nixos/profiles/role-dev.nix +++ b/nixos/profiles/role-dev.nix @@ -39,6 +39,7 @@ shfmt statix tmux + yt-dlp #unstable.aider-chat unstable.bottom unstable.cyme @@ -48,6 +49,7 @@ unstable.talosctl # overlay override unstable.zellij unstable.kitty + unstable.nodePackages_latest.prettier # code formatter # flake imports inputs.nix-inspect.packages.${pkgs.system}.default