diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..072eb55 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +hosts/lithium/semi-secret-vars.nix filter=git-agecrypt diff=git-agecrypt diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f2ccda5..0000000 --- a/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -result -result-* -localnotes.md -*.qcow2 \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 205df23..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "git.enabled": false -} \ No newline at end of file diff --git a/README.md b/README.md index e2a9b9e..89d5ab2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## Overview -This repository manages **multiple NixOS systems** using a shared modular configuration. +This repository maanges **multiple NixOS systems** using a shared modular configuration. It's designed to be **secure, composable, and automated** using modern Nix tooling. - **Laptop ("neon")**: Portable KVM/Swiss-Army Knife @@ -79,6 +79,9 @@ nix build .#nixosConfigurations.installIso.config.system.build.images.iso sudo mount -o loop result/iso/nixos-*.iso mnt ls mnt umount mnt + +# Manipulate sops-nix secrets +nix-shell -p sops --run "sops secrets/example.yaml" ``` ## Design Goals @@ -110,6 +113,10 @@ umount mnt ``` +## Configuring and Accessing Secrets + +I need to rip out agecrypt and go pure SOPS. + ## References - [@shazow](https://github.com/shazow/) and https://github.com/shazow/nixfiles/ diff --git a/flake.bak b/flake.bak new file mode 100644 index 0000000..6f3318a --- /dev/null +++ b/flake.bak @@ -0,0 +1,70 @@ +{ + description = "Configuration for NixOS"; + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + nixos-hardware.url = "github:nixos/nixos-hardware"; + home-manager.url = "github:nix-community/home-manager"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + sops-nix.url = "github:Mic92/sops-nix"; + sops-nix.inputs.nixpkgs.follows = "nixpkgs"; + + # flake-parts.url = "github:hercules-ci/flake-parts"; + }; + # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument + outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, ...}: + let + lib = import ./lib { inherit (nixpkgs) lib; }; + in + { + # NOTE: Run `nix flake show` to see what this flake has to offer. + # TODO: Enable automated formatting with numtide/treefmt-nix + # `nixos-rebuild switch --flake .#` + nixosConfigurations = { + neon = nixpkgs.lib.nixosSystem { + specialArgs = { inherit inputs; }; + system = "x86_64-linux"; + modules = [ + ./hosts/neon + ]; + }; + #lithium = nixpkgs.lib.nixosSystem { + #specialArgs = { inherit inputs; }; + #system = "x86_64-linux"; + #modules = [ + #./hosts/lithium + #]; + #}; + lithium = lib.mkSystem { + users = [ + { name = "jml"; } + ]; + }; + }; + homeConfigurations = { + "jml" = home-manager.lib.homeManagerConfiguration { + modules = [ + ./users/jml/home.nix + ]; + }; + }; + # TODO: Implement a dev shell for working on this repository. + # Personally I'm using hx, nil, and git-agecrypt + # The only thing totally necessary which isn't captured by the flake inputs + # is git-agecrypt so that should be included here or somehow in the flake. + devShells.x86_64-linux.default = pkgs.mkShell { + buildInputs = with pkgs; [ + nixpkgs-fmt + sops + age + git-agecrypt + ]; + shellHook = '' + echo "ready to rock" + ''; + }; + # `nix run .#name` and `nix build .#name` + # packages = {}; + # `home-manager switch` + # homeConfigurations = {}; + }; +} diff --git a/flake.lock b/flake.lock index 97d3db0..d40ebb3 100644 --- a/flake.lock +++ b/flake.lock @@ -1,80 +1,12 @@ { "nodes": { - "base16": { - "inputs": { - "fromYaml": "fromYaml" - }, - "locked": { - "lastModified": 1755819240, - "narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=", - "owner": "SenchoPens", - "repo": "base16.nix", - "rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6", - "type": "github" - }, - "original": { - "owner": "SenchoPens", - "repo": "base16.nix", - "type": "github" - } - }, - "base16-fish": { - "flake": false, - "locked": { - "lastModified": 1754405784, - "narHash": "sha256-l9xHIy+85FN+bEo6yquq2IjD1rSg9fjfjpyGP1W8YXo=", - "owner": "tomyun", - "repo": "base16-fish", - "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", - "type": "github" - }, - "original": { - "owner": "tomyun", - "repo": "base16-fish", - "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", - "type": "github" - } - }, - "base16-helix": { - "flake": false, - "locked": { - "lastModified": 1752979451, - "narHash": "sha256-0CQM+FkYy0fOO/sMGhOoNL80ftsAzYCg9VhIrodqusM=", - "owner": "tinted-theming", - "repo": "base16-helix", - "rev": "27cf1e66e50abc622fb76a3019012dc07c678fac", - "type": "github" - }, - "original": { - "owner": "tinted-theming", - "repo": "base16-helix", - "type": "github" - } - }, - "base16-vim": { - "flake": false, - "locked": { - "lastModified": 1732806396, - "narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=", - "owner": "tinted-theming", - "repo": "base16-vim", - "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", - "type": "github" - }, - "original": { - "owner": "tinted-theming", - "repo": "base16-vim", - "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", - "type": "github" - } - }, "crane": { "locked": { - "lastModified": 1754269165, - "narHash": "sha256-0tcS8FHd4QjbCVoxN9jI+PjHgA4vc/IjkUSp+N3zy0U=", + "lastModified": 1731098351, + "narHash": "sha256-HQkYvKvaLQqNa10KEFGgWHfMAbWBfFp+4cAgkut+NNE=", "owner": "ipetkov", "repo": "crane", - "rev": "444e81206df3f7d92780680e45858e31d2f07a08", + "rev": "ef80ead953c1b28316cc3f8613904edc2eb90c28", "type": "github" }, "original": { @@ -90,11 +22,11 @@ ] }, "locked": { - "lastModified": 1762276996, - "narHash": "sha256-TtcPgPmp2f0FAnc+DMEw4ardEgv1SGNR3/WFGH0N19M=", + "lastModified": 1758287904, + "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", "owner": "nix-community", "repo": "disko", - "rev": "af087d076d3860760b3323f6b583f4d828c1ac17", + "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", "type": "github" }, "original": { @@ -103,30 +35,14 @@ "type": "github" } }, - "firefox-gnome-theme": { - "flake": false, - "locked": { - "lastModified": 1758112371, - "narHash": "sha256-lizRM2pj6PHrR25yimjyFn04OS4wcdbc38DCdBVa2rk=", - "owner": "rafaelmardojai", - "repo": "firefox-gnome-theme", - "rev": "0909cfe4a2af8d358ad13b20246a350e14c2473d", - "type": "github" - }, - "original": { - "owner": "rafaelmardojai", - "repo": "firefox-gnome-theme", - "type": "github" - } - }, "flake-compat": { "flake": false, "locked": { - "lastModified": 1747046372, - "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "owner": "edolstra", "repo": "flake-compat", - "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { @@ -135,22 +51,6 @@ "type": "github" } }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1751685974, - "narHash": "sha256-NKw96t+BgHIYzHUjkTK95FqYRVKB8DHpVhefWSz/kTw=", - "ref": "refs/heads/main", - "rev": "549f2762aebeff29a2e5ece7a7dc0f955281a1d1", - "revCount": 92, - "type": "git", - "url": "https://git.lix.systems/lix-project/flake-compat.git" - }, - "original": { - "type": "git", - "url": "https://git.lix.systems/lix-project/flake-compat.git" - } - }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -159,11 +59,11 @@ ] }, "locked": { - "lastModified": 1754091436, - "narHash": "sha256-XKqDMN1/Qj1DKivQvscI4vmHfDfvYR2pfuFOJiCeewM=", + "lastModified": 1730504689, + "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "67df8c627c2c39c41dbec76a1f201929929ab0bd", + "rev": "506278e768c2a08bec68eb62932193e341f55c90", "type": "github" }, "original": { @@ -172,61 +72,21 @@ "type": "github" } }, - "flake-parts_2": { + "flake-utils": { "inputs": { - "nixpkgs-lib": [ - "nvf", - "nixpkgs" - ] + "systems": "systems" }, "locked": { - "lastModified": 1760948891, - "narHash": "sha256-TmWcdiUUaWk8J4lpjzu4gCGxWY6/Ok7mOK4fIFfBuU4=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "864599284fc7c0ba6357ed89ed5e2cd5040f0c04", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-parts_3": { - "inputs": { - "nixpkgs-lib": [ - "stylix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1756770412, - "narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "4524271976b625a4a605beefd893f270620fd751", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "fromYaml": { - "flake": false, - "locked": { - "lastModified": 1731966426, - "narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=", - "owner": "SenchoPens", - "repo": "fromYaml", - "rev": "106af9e2f715e2d828df706c386a685698f3223b", - "type": "github" - }, - "original": { - "owner": "SenchoPens", - "repo": "fromYaml", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, @@ -252,23 +112,6 @@ "type": "github" } }, - "gnome-shell": { - "flake": false, - "locked": { - "lastModified": 1748186689, - "narHash": "sha256-UaD7Y9f8iuLBMGHXeJlRu6U1Ggw5B9JnkFs3enZlap0=", - "owner": "GNOME", - "repo": "gnome-shell", - "rev": "8c88f917db0f1f0d80fa55206c863d3746fa18d0", - "type": "github" - }, - "original": { - "owner": "GNOME", - "ref": "48.2", - "repo": "gnome-shell", - "type": "github" - } - }, "home-manager": { "inputs": { "nixpkgs": [ @@ -276,11 +119,11 @@ ] }, "locked": { - "lastModified": 1762964643, - "narHash": "sha256-RYHN8O/Aja59XDji6WSJZPkJpYVUfpSkyH+PEupBJqM=", + "lastModified": 1759337100, + "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=", "owner": "nix-community", "repo": "home-manager", - "rev": "827f2a23373a774a8805f84ca5344654c31f354b", + "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3", "type": "github" }, "original": { @@ -301,42 +144,49 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1762205063, - "narHash": "sha256-If6vQ+KvtKs3ARBO9G3l+4wFSCYtRBrwX1z+I+B61wQ=", + "lastModified": 1737639419, + "narHash": "sha256-AEEDktApTEZ5PZXNDkry2YV2k6t0dTgLPEmAZbnigXU=", "owner": "nix-community", "repo": "lanzaboote", - "rev": "88b8a563ff5704f4e8d8e5118fb911fa2110ca05", + "rev": "a65905a09e2c43ff63be8c0e86a93712361f871e", "type": "github" }, "original": { "owner": "nix-community", - "ref": "v0.4.3", + "ref": "v0.4.2", "repo": "lanzaboote", "type": "github" } }, - "mnw": { + "microvm": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ], + "spectrum": "spectrum" + }, "locked": { - "lastModified": 1758834834, - "narHash": "sha256-Y7IvY4F8vajZyp3WGf+KaiIVwondEkMFkt92Cr9NZmg=", - "owner": "Gerg-L", - "repo": "mnw", - "rev": "cfbc7d1cc832e318d0863a5fc91d940a96034001", + "lastModified": 1758113222, + "narHash": "sha256-Q5i/qaj6v6F4N1Q5gI/4aL0IEEUE/LjQuwcA8L5IOMc=", + "owner": "astro", + "repo": "microvm.nix", + "rev": "b9206e245c07c0782beff58e1e94bb48b2531d15", "type": "github" }, "original": { - "owner": "Gerg-L", - "repo": "mnw", + "owner": "astro", + "repo": "microvm.nix", "type": "github" } }, "nixos-hardware": { "locked": { - "lastModified": 1762847253, - "narHash": "sha256-BWWnUUT01lPwCWUvS0p6Px5UOBFeXJ8jR+ZdLX8IbrU=", + "lastModified": 1759261527, + "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "899dc449bc6428b9ee6b3b8f771ca2b0ef945ab9", + "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f", "type": "github" }, "original": { @@ -345,13 +195,64 @@ "type": "github" } }, + "nixos-secrets": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1759474546, + "narHash": "sha256-ZOlrxrAb5x5yM13P16sZowXb8AbEH02cZxets6SmkkA=", + "ref": "refs/heads/main", + "rev": "b28dde5afb05bf107905eff5c38908463fde5c59", + "shallow": true, + "type": "git", + "url": "ssh://forgejo@git.garage.systems/jml/nixos-secrets.git" + }, + "original": { + "shallow": true, + "type": "git", + "url": "ssh://forgejo@git.garage.systems/jml/nixos-secrets.git" + } + }, "nixpkgs": { "locked": { - "lastModified": 1762977756, - "narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=", + "lastModified": 1757967192, + "narHash": "sha256-/aA9A/OBmnuOMgwfzdsXRusqzUpd8rQnQY8jtrHK+To=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0d7c15863b251a7a50265e57c1dca1a7add2e291", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1730741070, + "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1759381078, + "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55", + "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", "type": "github" }, "original": { @@ -361,75 +262,6 @@ "type": "github" } }, - "noctalia": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1764122160, - "narHash": "sha256-JZ51AW7zKgqlZp+oqt3Y7thglv23TPjgG1XiGBFWhr8=", - "owner": "noctalia-dev", - "repo": "noctalia-shell", - "rev": "3c5dfd87db582bf9056d83f41d53b90ba08023c6", - "type": "github" - }, - "original": { - "owner": "noctalia-dev", - "repo": "noctalia-shell", - "type": "github" - } - }, - "nur": { - "inputs": { - "flake-parts": [ - "stylix", - "flake-parts" - ], - "nixpkgs": [ - "stylix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1758998580, - "narHash": "sha256-VLx0z396gDCGSiowLMFz5XRO/XuNV+4EnDYjdJhHvUk=", - "owner": "nix-community", - "repo": "NUR", - "rev": "ba8d9c98f5f4630bcb0e815ab456afd90c930728", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "NUR", - "type": "github" - } - }, - "nvf": { - "inputs": { - "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts_2", - "mnw": "mnw", - "nixpkgs": [ - "nixpkgs" - ], - "systems": "systems" - }, - "locked": { - "lastModified": 1762622004, - "narHash": "sha256-NpzzgaoMK8aRHnndHWbYNKLcZN0r1y6icCoJvGoBsoE=", - "owner": "notashelf", - "repo": "nvf", - "rev": "09470524a214ed26633ddc2b6ec0c9bf31a8b909", - "type": "github" - }, - "original": { - "owner": "notashelf", - "repo": "nvf", - "type": "github" - } - }, "pre-commit-hooks-nix": { "inputs": { "flake-compat": [ @@ -440,14 +272,15 @@ "nixpkgs": [ "lanzaboote", "nixpkgs" - ] + ], + "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1750779888, - "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", + "lastModified": 1731363552, + "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", + "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", "type": "github" }, "original": { @@ -456,38 +289,16 @@ "type": "github" } }, - "quickshell": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1764045583, - "narHash": "sha256-W24ReyRrhOKTKIsuAMkY5hnVlCufGoONM79sjUoyQkk=", - "owner": "outfoxxed", - "repo": "quickshell", - "rev": "e9bad67619ee9937a1bbecfc6ad3b4231d2ecdc3", - "type": "github" - }, - "original": { - "owner": "outfoxxed", - "repo": "quickshell", - "type": "github" - } - }, "root": { "inputs": { "disko": "disko", "home-manager": "home-manager", "lanzaboote": "lanzaboote", + "microvm": "microvm", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs", - "noctalia": "noctalia", - "nvf": "nvf", - "quickshell": "quickshell", - "sops-nix": "sops-nix", - "stylix": "stylix" + "nixos-secrets": "nixos-secrets", + "nixpkgs": "nixpkgs_2", + "sops-nix": "sops-nix" } }, "rust-overlay": { @@ -498,11 +309,11 @@ ] }, "locked": { - "lastModified": 1761791894, - "narHash": "sha256-myRIDh+PxaREz+z9LzbqBJF+SnTFJwkthKDX9zMyddY=", + "lastModified": 1731897198, + "narHash": "sha256-Ou7vLETSKwmE/HRQz4cImXXJBr/k9gp4J4z/PF8LzTE=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "59c45eb69d9222a4362673141e00ff77842cd219", + "rev": "0be641045af6d8666c11c2c40e45ffc9667839b5", "type": "github" }, "original": { @@ -518,11 +329,11 @@ ] }, "locked": { - "lastModified": 1763069729, - "narHash": "sha256-A91a+K0Q9wfdPLwL06e/kbHeAWSzPYy2EGdTDsyfb+s=", + "lastModified": 1759188042, + "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=", "owner": "Mic92", "repo": "sops-nix", - "rev": "a2bcd1c25c1d29e22756ccae094032ab4ada2268", + "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d", "type": "github" }, "original": { @@ -531,38 +342,20 @@ "type": "github" } }, - "stylix": { - "inputs": { - "base16": "base16", - "base16-fish": "base16-fish", - "base16-helix": "base16-helix", - "base16-vim": "base16-vim", - "firefox-gnome-theme": "firefox-gnome-theme", - "flake-parts": "flake-parts_3", - "gnome-shell": "gnome-shell", - "nixpkgs": [ - "nixpkgs" - ], - "nur": "nur", - "systems": "systems_2", - "tinted-foot": "tinted-foot", - "tinted-kitty": "tinted-kitty", - "tinted-schemes": "tinted-schemes", - "tinted-tmux": "tinted-tmux", - "tinted-zed": "tinted-zed" - }, + "spectrum": { + "flake": false, "locked": { - "lastModified": 1762264356, - "narHash": "sha256-QVfC53Ri+8n3e7Ujx9kq6all3+TLBRRPRnc6No5qY5w=", - "owner": "nix-community", - "repo": "stylix", - "rev": "647bb8dd96a206a1b79c4fd714affc88b409e10b", - "type": "github" + "lastModified": 1754675037, + "narHash": "sha256-afS08F7lfMUBR4qrBxinN1kuxu+DoHQ5TPNVp9VS/OA=", + "ref": "refs/heads/main", + "rev": "586577f3015397afacd83bc185454f4cc3c8028f", + "revCount": 955, + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" }, "original": { - "owner": "nix-community", - "repo": "stylix", - "type": "github" + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" } }, "systems": { @@ -579,102 +372,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "tinted-foot": { - "flake": false, - "locked": { - "lastModified": 1726913040, - "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=", - "owner": "tinted-theming", - "repo": "tinted-foot", - "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", - "type": "github" - }, - "original": { - "owner": "tinted-theming", - "repo": "tinted-foot", - "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", - "type": "github" - } - }, - "tinted-kitty": { - "flake": false, - "locked": { - "lastModified": 1735730497, - "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=", - "owner": "tinted-theming", - "repo": "tinted-kitty", - "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa", - "type": "github" - }, - "original": { - "owner": "tinted-theming", - "repo": "tinted-kitty", - "type": "github" - } - }, - "tinted-schemes": { - "flake": false, - "locked": { - "lastModified": 1757716333, - "narHash": "sha256-d4km8W7w2zCUEmPAPUoLk1NlYrGODuVa3P7St+UrqkM=", - "owner": "tinted-theming", - "repo": "schemes", - "rev": "317a5e10c35825a6c905d912e480dfe8e71c7559", - "type": "github" - }, - "original": { - "owner": "tinted-theming", - "repo": "schemes", - "type": "github" - } - }, - "tinted-tmux": { - "flake": false, - "locked": { - "lastModified": 1757811970, - "narHash": "sha256-n5ZJgmzGZXOD9pZdAl1OnBu3PIqD+X3vEBUGbTi4JiI=", - "owner": "tinted-theming", - "repo": "tinted-tmux", - "rev": "d217ba31c846006e9e0ae70775b0ee0f00aa6b1e", - "type": "github" - }, - "original": { - "owner": "tinted-theming", - "repo": "tinted-tmux", - "type": "github" - } - }, - "tinted-zed": { - "flake": false, - "locked": { - "lastModified": 1757811247, - "narHash": "sha256-4EFOUyLj85NRL3OacHoLGEo0wjiRJzfsXtR4CZWAn6w=", - "owner": "tinted-theming", - "repo": "base16-zed", - "rev": "824fe0aacf82b3c26690d14e8d2cedd56e18404e", - "type": "github" - }, - "original": { - "owner": "tinted-theming", - "repo": "base16-zed", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 8fe78ea..682f169 100644 --- a/flake.nix +++ b/flake.nix @@ -5,118 +5,69 @@ nixos-hardware.url = "github:nixos/nixos-hardware"; home-manager.url = "github:nix-community/home-manager"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; - lanzaboote.url = "github:nix-community/lanzaboote/v0.4.3"; + lanzaboote.url = "github:nix-community/lanzaboote/v0.4.2"; lanzaboote.inputs.nixpkgs.follows = "nixpkgs"; sops-nix.url = "github:Mic92/sops-nix"; sops-nix.inputs.nixpkgs.follows = "nixpkgs"; disko.url = "github:nix-community/disko"; disko.inputs.nixpkgs.follows = "nixpkgs"; - stylix.url = "github:nix-community/stylix"; - stylix.inputs.nixpkgs.follows = "nixpkgs"; - - #obsidian-nvim.url = "github:epwalsh/obsidian.nvim"; - nvf = { - url = "github:notashelf/nvf"; - inputs.nixpkgs.follows = "nixpkgs"; - #inputs.obsidian-nvim.follows = "obsidian-nvim"; - }; - - quickshell = { - url = "github:outfoxxed/quickshell"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - noctalia = { - url = "github:noctalia-dev/noctalia-shell"; - inputs.nixpkgs.follows = "nixpkgs"; - inputs.quickshell.follows = "quickshell"; - }; + microvm.url = "github:astro/microvm.nix"; + microvm.inputs.nixpkgs.follows = "nixpkgs"; + nixos-secrets.url = "git+ssh://forgejo@git.garage.systems/jml/nixos-secrets.git?shallow=1"; + #nixos-secrets.flake = false; # TODO: Why does flake need to be false? + #nixos-secrets.inputs.nixpkgs.follows = "nixpkgs"; }; # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument - outputs = - inputs@{ - self, - nixpkgs, - nixos-hardware, - home-manager, - sops-nix, - lanzaboote, - disko, - stylix, - nvf, - ... - }: - let - zwLib = import ./lib { - inherit nixpkgs home-manager inputs; + outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, microvm, nixos-secrets, ...}: + let + mkSystem = (import ./lib { + inherit nixpkgs home-manager inputs; + }).mkSystem; + in + { + # NOTE: Run `nix flake show` to see what this flake has to offer. + # TODO: Enable automated formatting with something like numtide/treefmt-nix + nixosConfigurations = { + neon = mkSystem { + hostname = "neon"; + users = [ "jml" ]; }; - mkSystem = zwLib.mkSystem; - mkHome = zwLib.mkHome; - mkHomeConfigs = zwLib.mkHomeConfigs; - - # NOTE: Currently these are exclusively user-profiles which use home-manager. - # Their home-manager specific declarations are at ../users/${username}/home.nix - system = "x86_64-linux"; # TODO: Improve this from only static x86 to dynamic. - homeUserProfiles = { - jml = mkHome { - inherit system; # inputs; - username = "jml"; - extraModules = [ nvf.homeManagerModules.default ]; - }; + lithium = mkSystem { + hostname = "lithium"; + #specialArgs = {inherit inputs;}; + extraModules = [ + inputs.sops-nix.nixosModules.sops + inputs.nixos-secrets.nixosModules.private-config + ]; + #extraModules = [ microvm.nixosModules.host ]; + users = [ + "jml" + "breakglass" + ]; }; - in - { - lib = { - mkSystem = mkSystem; + titanium = mkSystem { + hostname = "titanium"; + users = [ + "jml" + ]; + extraModules = []; }; - # NOTE: Run `nix flake show` to see what this flake has to offer. - # TODO: Enable automated formatting with something like numtide/treefmt-nix - nixosConfigurations = { - neon = mkSystem { - hostname = "neon"; - users = [ "jml" ]; - }; - lithium = mkSystem { - hostname = "lithium"; - # extraModules = [ inputs.sops-nix.nixosModules.sops ]; - users = [ - "jml" - "breakglass" - ]; - }; - titanium = mkSystem { - hostname = "titanium"; - users = [ - "jml" - ]; - homeUsers = { - jml = homeUserProfiles.jml.module; - }; - #extraModules = [ (import ./overlays) ]; - # NOTE: If I'm using a home-manager configuration on a given host, - # I also need to include the relevant modules. - # TODO: Can I instead self-reference the homeConfigurations in this flake? - extraModules = [ - stylix.nixosModules.stylix - ]; - }; - cobalt = mkSystem { - hostname = "cobalt"; - users = [ "jml" ]; - }; - # `nix build .#nixosConfigurations.installIso.config.system.build.isoImage` - # https://github.com/nix-community/nixos-generators - installIso = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" - ]; - specialArgs = { inherit inputs; }; - }; + # `nix build .#nixosConfigurations.installIso.config.system.build.isoImage` + # https://github.com/nix-community/nixos-generators + installIso = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + ]; + specialArgs = {inherit inputs;}; + }; + }; + homeConfigurations = { + "jml" = home-manager.lib.homeManagerConfiguration { + modules = [ + ./users/jml/home.nix + ]; }; - - # For Debugging: `home-manager build --flake .` or `nix build .#homeConfigurations."jml".activationPackage` - # `home-manager switch --flake .#jml` - # https://nix-community.github.io/home-manager/options.xhtml - homeConfigurations = mkHomeConfigs homeUserProfiles; }; + }; } diff --git a/git-agecrypt.toml b/git-agecrypt.toml new file mode 100644 index 0000000..b2ff6dc --- /dev/null +++ b/git-agecrypt.toml @@ -0,0 +1,2 @@ +[config] +"hosts/lithium/semi-secret-vars.nix" = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP2SVmZ3iJF/rviKhTgkZOvu1fWr6G29K4u6yaxjZn4H jay@lithium"] diff --git a/hosts/cobalt/README.md b/hosts/cobalt/README.md deleted file mode 100644 index 5f1169c..0000000 --- a/hosts/cobalt/README.md +++ /dev/null @@ -1,21 +0,0 @@ - -Device Specific Hardware Details` -```shell -[nix-shell:~]$ lspci -nn -00:00.0 Host bridge [0600]: Intel Corporation Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers [8086:5904] (rev 02) -00:02.0 VGA compatible controller [0300]: Intel Corporation HD Graphics 620 [8086:5916] (rev 02) -00:04.0 Signal processing controller [1180]: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem [8086:1903] (rev 02) -00:14.0 USB controller [0c03]: Intel Corporation Sunrise Point-LP USB 3.0 xHCI Controller [8086:9d2f] (rev 21) -00:14.2 Signal processing controller [1180]: Intel Corporation Sunrise Point-LP Thermal subsystem [8086:9d31] (rev 21) -00:15.0 Signal processing controller [1180]: Intel Corporation Sunrise Point-LP Serial IO I2C Controller #0 [8086:9d60] (rev 21) -00:15.1 Signal processing controller [1180]: Intel Corporation Sunrise Point-LP Serial IO I2C Controller #1 [8086:9d61] (rev 21) -00:16.0 Communication controller [0780]: Intel Corporation Sunrise Point-LP CSME HECI #1 [8086:9d3a] (rev 21) -00:17.0 SATA controller [0106]: Intel Corporation Sunrise Point-LP SATA Controller [AHCI mode] [8086:9d03] (rev 21) -00:1c.0 PCI bridge [0604]: Intel Corporation Sunrise Point-LP PCI Express Root Port #1 [8086:9d10] (rev f1) -00:1c.5 PCI bridge [0604]: Intel Corporation Sunrise Point-LP PCI Express Root Port #6 [8086:9d15] (rev f1) -00:1f.0 ISA bridge [0601]: Intel Corporation Sunrise Point-LP LPC Controller [8086:9d58] (rev 21) -00:1f.2 Memory controller [0580]: Intel Corporation Sunrise Point-LP PMC [8086:9d21] (rev 21) -00:1f.3 Audio device [0403]: Intel Corporation Sunrise Point-LP HD Audio [8086:9d71] (rev 21) -00:1f.4 SMBus [0c05]: Intel Corporation Sunrise Point-LP SMBus [8086:9d23] (rev 21) -02:00.0 Network controller [0280]: Intel Corporation Wireless 8260 [8086:24f3] (rev 3a) -``` diff --git a/hosts/cobalt/boot.nix b/hosts/cobalt/boot.nix deleted file mode 100644 index e1f16ff..0000000 --- a/hosts/cobalt/boot.nix +++ /dev/null @@ -1,6 +0,0 @@ -{}: -{ - # Default to systemd-boot - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; -} \ No newline at end of file diff --git a/hosts/cobalt/configuration.nix b/hosts/cobalt/configuration.nix deleted file mode 100644 index 79d1f95..0000000 --- a/hosts/cobalt/configuration.nix +++ /dev/null @@ -1,26 +0,0 @@ -# Edit this configuration file to define what should be installed on -# your system. Help is available in the configuration.nix(5) man page -# and in the NixOS manual (accessible by running ‘nixos-help’). - -{ config, pkgs, ... }: - -{ - networking.hostName = "cobalt"; # Define your hostname. - # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. - networking.networkmanager.enable = true; - - - services.xserver.xkb = { - layout = "us"; - variant = ""; - }; - - fonts.packages = with pkgs; [ - nerd-fonts.fira-code - nerd-fonts.iosevka - atkinson-hyperlegible - ]; - - - system.stateVersion = "25.05"; -} diff --git a/hosts/cobalt/default.nix b/hosts/cobalt/default.nix deleted file mode 100644 index d60b1f2..0000000 --- a/hosts/cobalt/default.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ inputs, ... }: -{ - imports = [ - ./boot.nix - ../../modules/nixos/base.nix - ../../modules/nixos/audio.nix - #../../modules/nixos/desktop.nix - # https://github.com/NixOS/nixos-hardware/blob/master/README.md#using-nix-flakes-support - # TODO: This module doesn't exist yet. - #inputs.nixos-hardware.nixosModules.asus-zenbook-ux390u - /home/jml/Workspace/nixos-hardware/asus/zenbook/ux390ua - ./hardware-configuration.nix - ./configuration.nix - ../../modules/nixos/gaming.nix - ../../modules/nixos/desktop/xfce - #../../modules/nixos/desktop/niri - ]; - - zw.gaming.enable = true; -} diff --git a/hosts/cobalt/hardware-configuration.nix b/hosts/cobalt/hardware-configuration.nix deleted file mode 100644 index da7f0e2..0000000 --- a/hosts/cobalt/hardware-configuration.nix +++ /dev/null @@ -1,41 +0,0 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - -{ - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/959b3c06-58a2-45be-b2d6-275c489c31f8"; - fsType = "ext4"; - }; - - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/2EC2-D03D"; - fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; - }; - - swapDevices = - [ { device = "/dev/disk/by-uuid/0239ee2a-484b-4a17-b1e9-02fd35df851f"; } - ]; - - # 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 - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.enp0s20f0u1u3.useDHCP = lib.mkDefault true; - # networking.interfaces.wlp2s0.useDHCP = lib.mkDefault true; - - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; -} diff --git a/hosts/lithium/README.md b/hosts/lithium/README.md index a73e9e8..1cdad59 100644 --- a/hosts/lithium/README.md +++ b/hosts/lithium/README.md @@ -7,29 +7,20 @@ This is my primary homelab host/NAS, previously powered by TrueNAS Scale/k3s. Even with fully declarative Nix/Nixpkgs/NixOS at the end of the day there are still some actions that need to be taken manually. -- secrets configuration for `sops-nix` +- secrets configuration (both for SOPS and git-agecrypt semi-secrets) - kanidm user management - tailscale auth key - jellyfin configuration via web-ui -## Secrets and "Private Information" +## Semi-Secrets -Originally I had used two providers of secrets, `sops-nix` and `git-agecrypt`, -and the reasoning for that was, with `git-agecrypt` I could directly encrypt an -entire `.nix` file, and use it to conceal an arbitrary amount of my nix config. -The #1 thing I was using it for was hiding details about the domain names that -power various services. I know that's not real security, and domains aren't -really private, but server logs prove that not including a domain in a GH repo -means you get dramatically fewer spurious requests. +`semi-secret-vars.nix` is using [git-agecrypt](https://github.com/vlaci/git-agecrypt) +and following a pattern I discovered here: + - https://github.com/nyawox/arcanum/blob/4629dfba1bc6d4dd2f4cf45724df81289230b61a/var/README.md + - https://github.com/vlaci/git-agecrypt -The reason for using `git-agecrypt` against a whole nix file like that was most -importantly because it allowed me to *just use nix variables*. Compared to the -invocationss SOPS & `sops-nix` require, it can be a lot more simple for setting -values like a domain name. +Essentially there are some details I won't want exposed in the repository, but +I do want them available to all my nix modules. The main one being the domain. -Now I'm going all in on `sops-nix` as the exclusive manager of secrets, and -maintaining a separate flake which contains private nix configuration details. -There are still issues with this, and now my overall nix config is essentially -fractured between "flake-A" and "flake-B", which gives me all the same issues -that any other software project faces with that arrangement. But I dislike -using `git-agecrypt` even more than I dislike those problems. +While it's not really a secret in the way a password is, consider this effort a +mitigation against ddos attacks and automated requests and login attempts. diff --git a/hosts/lithium/boot.nix b/hosts/lithium/boot.nix deleted file mode 100644 index e1f16ff..0000000 --- a/hosts/lithium/boot.nix +++ /dev/null @@ -1,6 +0,0 @@ -{}: -{ - # Default to systemd-boot - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; -} \ No newline at end of file diff --git a/hosts/lithium/configuration.nix b/hosts/lithium/configuration.nix index a18dc08..ab3a8d6 100644 --- a/hosts/lithium/configuration.nix +++ b/hosts/lithium/configuration.nix @@ -1,7 +1,8 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { - sops.defaultSopsFile = ./secrets/common.yaml; + #sops.defaultSopsFile = ./secrets/common.yaml; networking.hostName = "lithium"; + networking.domain = lib.mkForce config.vars.domain; environment.systemPackages = with pkgs; [ zfs ]; diff --git a/hosts/lithium/default.nix b/hosts/lithium/default.nix index 30fbf84..8eb2f37 100644 --- a/hosts/lithium/default.nix +++ b/hosts/lithium/default.nix @@ -1,16 +1,47 @@ { inputs, ... }: +#let + #secretsPath = builtins.toString inputs.nixos-secrets; +#in { + #sops = { + #defaultSopsFile = "${secretsPath}/${config.hostname}/secrets.yaml"; + #defaultSopsFile = "${secretsPath}/global/secrets.yaml"; + #}; + imports = [ - ./boot.nix ../../modules/nixos/base.nix - inputs.sops-nix.nixosModules.sops + #inputs.sops-nix.nixosModules.sops + #import ./sops.nix ( {inherit inputs;} ) + ./sops.nix ./hardware.nix ./configuration.nix + ./semi-secret-vars.nix + ./services/caddy.nix ./services/tailscale.nix ./services/kanidm.nix ./services/jellyfin.nix ./services/uptime-kuma.nix ./services/file-shares.nix + ./services/miniflux + ./services/forgejo.nix + + ./services/immich.nix + + ./services/calibre-web.nix + + # Monitoring + ./services/monitoring + ./services/smartd.nix + + # Game Servers + ./services/palworld + + # TODO: Add Karakeep with yt-dlp + https://news.ycombinator.com/item?id=45595084 + + # Services running in virtual machines + #./microvms + #./microvms/palworld ]; + } diff --git a/hosts/lithium/microvms/default.nix b/hosts/lithium/microvms/default.nix new file mode 100644 index 0000000..3467e4c --- /dev/null +++ b/hosts/lithium/microvms/default.nix @@ -0,0 +1,18 @@ +{ config, pkgs, lib, ... }: +{ + microvm.autostart = [ + "palworld-server" + ]; + + microvm = { + interfaces = [ + { type = "user"; id = "main-net"; } + { type = "macvtap"; id = "vm-palworld"; } + ]; + + # Interface Name on the Host + # Ethernet Address of MicroVM's interface. + # Locally administered have one of 2/6/A/E in the second nibble. + #interfaces = [{type = "tap";id = "vm-palworld";mac = "02:00:00:00:00:01";}]; + }; +} diff --git a/hosts/lithium/microvms/palworld/default.nix b/hosts/lithium/microvms/palworld/default.nix new file mode 100644 index 0000000..f20e293 --- /dev/null +++ b/hosts/lithium/microvms/palworld/default.nix @@ -0,0 +1,107 @@ +{ config, pkgs, lib, ... }: +{ + # Host Firewall + networking.firewall.allowedUDPPorts = [ 8211 ]; + #networking.nat = { + #enable = true; + #enableIPv6 = true; + #externalInterface = "eth0"; + #internalInterfaces = [ "microvm" ]; + #}; + + microvm.vms.palworld-server = { + # Basic Requirements + # https://docs.palworldgame.com/getting-started/requirements + #hypervisor = "qemu"; + vcpu = 4; + memory = 16348; + + # Networking + interfaces = [{ type = "user"; id = "main-net"; }]; + + # Interface Name on the Host + # Ethernet Address of MicroVM's interface. + # Locally administered have one of 2/6/A/E in the second nibble. + #interfaces = [{type = "tap";id = "vm-palworld";mac = "02:00:00:00:00:01";}]; + #forwardPorts = [ + #{ proto = "udp"; from = "host"; host.port = 8211; guest.port = 8211; } + # Optional: If you need RCON or other ports, add them here + # { proto = "tcp"; from = "host"; host.port = 25575; guest.port = 25575; } + #]; + + # Persistent Data + sharedDirectories = [ + { + source = "/var/lib/palworld-data"; + target = "/var/lib/palworld-server"; + readonly = false; + } + ]; + + # VM NixOS Configuration + config = { + imports = [ pkgs.nixosModules.notDetected ]; + + networking.hostName = "palworld-vm"; + time.timeZone = "America/Chicago"; + + environment.systemPackages = with pkgs; [ + steamcmd + #glibc + #gnumake + #cff + ]; + + # Pre-VM-Start + binScripts.tap-up = lib.mkAfter '' + ${lib.getExe' pkgs.iproute2 "ip"} link set dev 'vm-ixp-as11201p' master 'ixp-peering' + ''; + + # Service Definition + systemd.services.palworld-dedicated = { + description = "Palworld Dedicated Server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + Type = "simple"; + User = "palworld"; + Group = "palworld"; + # Working Directory points to where steamcmd installs the server + WorkingDirectory = "/var/lib/palworld-server/Pal/Binaries/Win64"; + ExecStart = '' + ${pkgs.steam-run}/bin/steam-run ${pkgs.bash}/bin/bash -c '\ + ${pkgs.steamcmd}/bin/steamcmd \ + +force_install_dur /var/lib/palworld-server \ + +login anonymous \ + +app_update 2394010 validate \ + +quit \ + && \ + ./PalServer.sh -userperfthreads -NoAsyncLoadingThread -UseNvidiaServers -nosteamclient \ + -Players=8 -Port=8211 -queryport=27015 -PublicPort=8211 -PublicIP=\"\" -RCONEnabled=False + ' + ''; + Restart = "on-failure"; + RestartSec = "5s"; + LimitNPROC = 10000; + LimitNOFILE = 100000; + }; + }; + + # User and Group Configuration + users.users.palworld = { + isSystem = true; + group = "palworld"; + createHome = false; + }; + users.groups.palworld = {}; + + # Firewall Configuration + networking.firewall.allowedUDPPorts = [ 8211 ]; + + # Ensure correct permissions for shared directory + systemd.tmpfiles.rules = [ + "d /var/lib/palworld-server 0755 palworld palworld -" + ]; + }; + }; +} diff --git a/hosts/lithium/microvms/valheim.nix b/hosts/lithium/microvms/valheim.nix new file mode 100644 index 0000000..e4a2f89 --- /dev/null +++ b/hosts/lithium/microvms/valheim.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: +{ + microvm.vms.valheim = { + autoStart = true; + memorySize = 4096; + vcpu = 2; + + forwardPorts = [ + { from = "host"; hostPort = 2456; guestPort = 2456; proto = "udp"; } + { from = "host"; hostPort = 2457; guestPort = 2457; proto = "udp"; } + ]; + + # NOTE: For games with large save files, choose a path in "/tank" for + # storage. + sharedDirectories = [ + { + hostPath = "/srv/game-data-valheim"; + guestPath = "/data"; + tag = "valheim-data"; + readOnly = false; + } + ]; + + packages = [ pkgs.steamcmd pkgs.steam-run ]; + + users.users.valheim = { + isNormalUser = true; + home = "/home/valheim"; + extraGroups = [ "wheel" ]; + }; + + systemd.services.valheim = { + description = "Valheim Dedicated Server"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + workingDirectory = "/data"; + ExecStart = '' + ${pkgs.steam-run}/bin/steam-run ./valheim_server.x86_64 \ + -name "Valheim NixOS" \ + -port 2456 \ + -world "FlatEarth" \ + -password "secret" \ + -public 1 + ''; + Restart = "always"; + User = "valheim"; + }; + }; + }; +} diff --git a/hosts/lithium/private-config.nix b/hosts/lithium/private-config.nix new file mode 100644 index 0000000..da79603 --- /dev/null +++ b/hosts/lithium/private-config.nix @@ -0,0 +1,8 @@ +{ inputs, ... }: +# let secretsPath = builtins.toString inputs.nixos-secrets; in +{ + #imports = [ inputs.nixos-secrets.nixosModules.private-config ]; + + # Enables a whole littany of private settings. + private-config.enable = true; +} diff --git a/hosts/lithium/secrets/common.yaml b/hosts/lithium/secrets/common.yaml index 341bc36..e02b06c 100644 --- a/hosts/lithium/secrets/common.yaml +++ b/hosts/lithium/secrets/common.yaml @@ -1,27 +1,30 @@ kanidm: - admin-password: ENC[AES256_GCM,data:wNE9qWAjfp8tf29sn1Q6GYrbw8g=,iv:uzg971jGIVyEkEbcOm2W8dy4wVgWiL+4Ph/f/bnieI0=,tag:/yY1okvnJLYGw2OLBd2Zdg==,type:str] - idm-admin-password: ENC[AES256_GCM,data:jIWaXUgHjhp0bP/DrF1m+plzcvE=,iv:nNpIkg9FTbCncih1/pAk4o7teuk7Gf/nPXyrnpFx4no=,tag:WhhsjtEdyS3Zw4F7uF9APg==,type:str] + admin-password: ENC[AES256_GCM,data:Hvmo6YG2ZCoYdQOBOyPiS2XAm6I=,iv:qKu5vlT0HEqK3Mx3zgAA0OUA+B63rEXnq/P059mrweI=,tag:K+iTc8R30ClP8egzIEtXKA==,type:str] + idm-admin-password: ENC[AES256_GCM,data:Dvz2o6gY/G3igJFhaIQ4gj/OG/8=,iv:hDE+y8SKqRU8tNxnd7q4CE3GfOHOkMcODpqc43KiPfc=,tag:fU8AyFokVUhERUvi6W6bYw==,type:str] +forgejo-admin-password: ENC[AES256_GCM,data:d7a2pzSpaeZ0CQ==,iv:XB6Y41egclWzmyZe3g2Z9U1NcCilw3VTZNlym94h3IU=,tag:vR6jrXiBciPXzUmvxHzQNw==,type:str] +miniflux: + oauth2_client_secret: ENC[AES256_GCM,data:tZk6Ru5MQk+VJ/ulZNtKirL2lfLmOeVKsDbJfLly1SBwXC6HdjBx+yAFCc7YVX+2,iv:GIIMhV/sIALjoUZsMMXAJl968owAlULJ1JLpShqa3RM=,tag:c2i+LvGJKQm82fsUEHF/BA==,type:str] sops: age: - recipient: age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5cFlReGMxV1R3QW1Vd1RU - WTgzNm5tbGhld3RMTGpMU1M2eVdoU0hmZGtNCmZLSTNOMk9IMDh6K2svRmRveGw3 - dlFUZ2lzTDBJWnBSTEhVTmVDOHVTdW8KLS0tIDhLWVZWSVJYM2x4YTlZWWZZZVNh - T2drb0p6TjZrZldpU0VUd0xmcVJUSk0KMjX3vr/74/HU7fmulefUHiNzwX8LcAes - ob3fabhMk9lmbuQk21rpoWbz3PNTfCQH63q+h7gLJTCCW2ISTvh/KQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4WUlyeStvZ28xVmV4VlNK + d1J1Z0twaTFzSEFENit0S210eTJFYTR1c1FRCnQvcFRCMUtFMkJxUDlRUTNxcTlK + dE5aM3U4Y0xvRE5jZlhrbjVtVk5rOHMKLS0tIHZISVlVcW9yT3hWcUtsVmN5TmRv + bXk5aSs4Wk9nM1p5d3FVSFBFKzVYZVEKYP2KQZIYm+zuI6OTfy85cEhj3gJWoKNu + jxd8vxwSbDmsXQK+mT8MsA9s+A9AhzGcZQ0rIQM/yKWFKSXt4kJ9rg== -----END AGE ENCRYPTED FILE----- - recipient: age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpK3VvNUhHNmJUQVZlREJl - c1oyZWx4ekNEM0VqL3NKanNmSmZtQXNpcWdVCmpWcklLVnhWUisvcGZzV1NHN3p4 - bW4wL09wL01XaHpveGdmbU4rbEp5NmsKLS0tIElhQVRmS05xUmJIZlI0S1dyWGhV - OGtKdHVwbWY2akJTQkF4YzlnNWQzNU0K81PyJ1tOvwOohNu9iUkS8vE7UXFRnJab - 8OLHtzX7FrkIH8rO2D5vEL9gPmxUtNKc9Ad3sndQls/yfg4wJAYedA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHQk1kYjU1bXZ0aUc3cGVQ + N1hwclNpRkJWQlVhaU9EOEFNRkRQMmhLakNjCjAwbE1UYkxxbzNxQjV5Y1I0TU0r + cmZBUTZsTzMxZmFZZUxnRmw3T205aDAKLS0tIGdJTHBHVmk4TmlBQ1RHYkJ3aWw3 + bktSejFIdS8wS2R4RHRFMEwwb2pBN1kK8EoLo1E/DiFmpCf/v0kGLPcqIB1qZDd1 + Uf7ccMFqvQH8wGVuyqqwiZ2SconvK7hHC5U9qgi6bZa/t4aW8eeU/g== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-06-07T02:02:46Z" - mac: ENC[AES256_GCM,data:7mWOon8Hs2oU40l1dx4tVE8yXgcKoxfUAzY8zbtTzXqCOhzTzhY4OZAZiu4RiUSIOm7dMdQbH9zSx0j+5e2k9QflfJDDM3rWfunTa7L8Bm8k9b/WjS0Fnb7OV0InO6tLxQwkTamMcc7ORrKxwHB5PwuXD+efeWNXveHo5GYgF+M=,iv:seh2Pzt+AmmxyD5hwh3VkLQTDMq0Gh9mV6J3QrtxcmM=,tag:jpXn2fht8wArB2KD/ZmbyA==,type:str] + lastmodified: "2025-10-03T06:48:03Z" + mac: ENC[AES256_GCM,data:tglsrKi8Ydifc08LLA/KHzqWI3u9+Tn9kkERI3XKp/vSy4a90T2fU9f/lcyYbOXXuOOCL364wYq7ETmsTzOmb5Eo2Wtcu9Hsn820rLXuxNu7kyz9os/0eL/IThrPQtKov4/IdzoGQCqZvd9kcxTN1UPlRnd9aiHwsKmoFFFNZlE=,iv:y9+JQRXZf/6GabaQ1nQk3dL7qKMQxyzvIsXU2yVmlZo=,tag:klmWeIP068BpsSi8u/tE4A==,type:str] unencrypted_suffix: _unencrypted version: 3.10.2 diff --git a/hosts/lithium/secrets/miniflux_admin_credentials.env b/hosts/lithium/secrets/miniflux_admin_credentials.env new file mode 100644 index 0000000..669e8fc --- /dev/null +++ b/hosts/lithium/secrets/miniflux_admin_credentials.env @@ -0,0 +1,10 @@ +ADMIN_USERNAME=ENC[AES256_GCM,data:1b9RG0hCr3mV+Q==,iv:+P9LxMk7gLvCvVgrzRgHhk7s3kMnMNkWyT8cyBe0msI=,tag:2TVfhdVToEsz4mF/UrrP9w==,type:str] +ADMIN_PASSWORD=ENC[AES256_GCM,data:3HUEKnmGJ9vRSA==,iv:UpY8iFBIT01QUFINo3Cn7dT6q0uDbbDNuU2K7hjfaRY=,tag:LizvS3rkk7PHQVTLRtmbqw==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0TWxwa21pNmxJczd1Y3l2\nZjIzYWJ2TEk0VlZGTXN2a3lvaGR3Q2cwNXlBClN5dXJyMmxFWnA5UytVUjErZ1Ju\nZHY5emdBd2plM1dvRWNwaE5ydW9IbGcKLS0tIEFtUFZnUkllajhDVTU4ejlTN09n\nN0VTWi9lb1UxQm1OTGwzU2dkc25XR1EKlsqqZCJ6YTseRoxaoQRcnnqg0Q6zDezP\ni8lVt4WCK/mIXiqASNf0EaunujxftSg4g5s1PoUzdh2RWRXjjUk6Rw==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_0__map_recipient=age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu +sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCY1pnNWdpUGNmTXQ5VHY4\nazJaSUVnMEd4cTVIa3p1NWJBWHAyMEhuMXprCjk3MENuUDJ3OE13bUhJKzNxV1Yr\nZmMwMUtyZldodDRBRkRIUnN5cCswVHcKLS0tIE43RmFHQU0zMitrcmtKaGRMTXZZ\nZWdCOHNVaXp2WjNWUUtTNmVjQTdQMkUK7dbXoDOAxppQi3nmp0S7q130BBvxtdo/\nuaC5FuUXijp0U+Xrdkq3Qukv/u4b7E17mw3zMgHIaxf8w0W/XmTcXQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_1__map_recipient=age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl +sops_lastmodified=2025-07-22T01:07:11Z +sops_mac=ENC[AES256_GCM,data:I17CIK+OqttRpVc9U3Xdefnb95PFcFpCykLSxoVvO74NCvYcHYaB09Wnbt5X46u3TtX1ZmDr85WNzWocu+rM1kdJFXnGI/N9UiCgnam66QCwIlIckCldDGsnPbHpkeB7SFgCJ+1GOz19poPu2RJ41b28NRxNdV4+9HB15Xz6OcM=,iv:7u28+i8HA6wv9SuTSjCGr5o0Wak6zmUvSj3z3CzxT6U=,tag:GXEbSyBGkPSveD0zREBEyQ==,type:str] +sops_unencrypted_suffix=_unencrypted +sops_version=3.10.2 diff --git a/hosts/lithium/semi-secret-vars.nix b/hosts/lithium/semi-secret-vars.nix new file mode 100644 index 0000000..1598e07 --- /dev/null +++ b/hosts/lithium/semi-secret-vars.nix @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 rhvgyQ 8V5ehsrqPR8s2joIfdpZRYDQpwH5BXI1GgQ/Qcb/Wg4 +ZKRZkXT0uPbXzuXLsteW31GsKzZy1deUl1GdWeQB+4U +-> "f&DjVar +Lhe9DbPHOqqKQ9HDhJB2xbIkrsxFGm39Yzr1J+ZbJnWYx5FCdGCCIexmv3GJy94t + +--- qKkjS2aEWavCLldEwi4MUTlDoQuIu9tSRr5yoeZVQhs +bZ~lU"Up v$?;:Zu҅^ŊQ/MBɉf]Ξ)4PY-߅ܻ ؟l&e2OUqXMDS7E&usU#d#؂W9^k.07hs4CRIwU aʯMwiUrikb}yV>r[8s \ No newline at end of file diff --git a/hosts/lithium/services/README.md b/hosts/lithium/services/README.md new file mode 100644 index 0000000..0bf9c37 --- /dev/null +++ b/hosts/lithium/services/README.md @@ -0,0 +1,11 @@ +# hosts/lithium/services + +The idea is that each `*.nix` or each `./*/default.nix` file would contain all +necessary details for a service to bring itself up and be running. + +One thing I have overlooked thus far is nothing tests for the existence of a +reverse proxy and bails out if one isn't available. Practically if caddy isn't +running, most of these services should also not run, or at the very least, the +blocks pertaining to setting up reverse proxy details don't need to run. + +There's a way of doing that with things like lib.mkDefault and so forth. diff --git a/hosts/lithium/services/acme-dns.nix b/hosts/lithium/services/acme-dns.nix new file mode 100644 index 0000000..9377497 --- /dev/null +++ b/hosts/lithium/services/acme-dns.nix @@ -0,0 +1,65 @@ +{ config, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + certDir = config.security.acme.certs."${homelabDomain}".directory; +in +{ + sops.secrets."cloudflare/dns_api_token" = { + mode = "0440"; + group = config.services.caddy.group; + restartUnits = [ "caddy.service" "ddclient.service" ]; + }; + + + # TODO: Consider defining reverse proxy all in one location. + # All the ports and domains would be visible in one place. + security.acme = { + acceptTerms = true; + defaults = { + # NOTE: Uncomment the following line for testing, comment for production. + server = "https://acme-staging-v02.api.letsencrypt.org/directory"; + dnsProvider = "cloudflare"; + dnsResolver = "1.1.1.1:53"; + dnsPropagationCheck = true; + credentialFiles = { + CLOUDFLARE_DNS_API_TOKEN_FILE = config.sops.secrets."cloudflare/dns_api_token".path; + }; + group = config.services.caddy.group; + #reloadServices = [ "caddy" ]; + email = "admin+acme@${homelabDomain}"; # NOTE: This email is /dev/null; + #keyType = "ec384"; + }; + }; + + services.ddclient = { + enable = true; + protocol = "cloudflare"; + usev4 = "webv4, webv4=https://cloudflare.com/cdn-cgi/trace, web-skip='ip='"; + username = "token"; + #secretsFile = config.sops.secrets."cloudflare/dns_api_token".path; + passwordFile = config.sops.secrets."cloudflare/dns_api_token".path; + zone = homelabDomain; + domains = [ + homelabDomain + "*.${homelabDomain}" + "id.${homelabDomain}" + "status.${homelabDomain}" + "grafana.${homelabDomain}" + "feeds.${homelabDomain}" + "git.${homelabDomain}" + "tv.${homelabDomain}" + "demo.${homelabDomain}" # Testing to see if the DNS record is set. + ]; + }; + + # NOTE: Issue a single cert /w subdomain wildcard + # At the expense of individual service security, some public details about + # attack surface remain slightly more private in https://crt.sh/ + security.acme.certs."${homelabDomain}" = { + #group = config.services.caddy.group; + domain = "${homelabDomain}"; + extraDomainNames = [ "*.${homelabDomain}" ]; + }; + # Nginx useACMEHost provides the DNS-01 challenge. + # security.acme.certs."${homelabDomain}".directory +} diff --git a/hosts/lithium/services/audiobookshelf.nix b/hosts/lithium/services/audiobookshelf.nix new file mode 100644 index 0000000..92cf710 --- /dev/null +++ b/hosts/lithium/services/audiobookshelf.nix @@ -0,0 +1,20 @@ +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + svcDomain = "audiobooks.${homelabDomain}"; + svcPort = config.services.audiobookshelf.port; # Prevent a Conflict +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${svcPort} + ''; + + services.audiobookshelf = { + enable = true; + openFirewall = true; + port = 8000; + + # NOTE: Path to AudioBookShelf config & metadata inside of `/var/lib` + dataDir = "audiobookshelf"; + }; +} diff --git a/hosts/lithium/services/caddy.nix b/hosts/lithium/services/caddy.nix index 86a39cf..862c7ce 100644 --- a/hosts/lithium/services/caddy.nix +++ b/hosts/lithium/services/caddy.nix @@ -1,13 +1,22 @@ -{ config, pkgs, ... }: +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + certDir = config.security.acme.certs."${homelabDomain}".directory; +in { - sops.secrets.caddy_env = { - sopsFile = ../secrets/caddy.env; - format = "dotenv"; + services.nginx.enable = lib.mkForce false; + + sops.secrets.cloudflare_env = { mode = "0440"; - owner = config.services.caddy.user; + sopsFile = "${inputs.nixos-secrets}/lithium/cloudflare.env"; + format = "dotenv"; group = config.services.caddy.group; restartUnits = [ "caddy.service" ]; }; + + # TODO: Revert to using Caddy DNS for the whole thing. + # TODO: Add another cloudflare DDNS provider. + # TODO: Add Metrics with Prometheus & Grafana services.caddy = { enable = true; package = pkgs.caddy.withPlugins { @@ -16,26 +25,33 @@ "github.com/mholt/caddy-dynamicdns@v0.0.0-20250430031602-b846b9e8fb83" "github.com/caddy-dns/cloudflare@v0.2.1" ]; - - # NOTE: Built on 6/4/2025 - hash = "sha256-swskhAr7yFJX+qy0FR54nqJarTOojwhV2Mbk7+fyS0I="; + # NOTE: Built on 9/30/2025 + hash = "sha256-xuwNkxZop+RnzFtM9DEwah95nPSyx8KgM+Eu4EJ9kqI="; }; # NOTE: Use Staging CA while testing, check `systemctl status caddy` # to see if everything is working. # acmeCA = "https://acme-staging-v02.api.letsencrypt.org/directory"; - - # TODO: Add Metrics with Prometheus & Grafana - environmentFile = config.sops.secrets.caddy_env.path; + + environmentFile = config.sops.secrets.cloudflare_env.path; + # NOTE: DNS provider settings + # https://caddy.community/t/how-to-use-dns-provider-modules-in-caddy-2/8148 globalConfig = '' - # acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN} + #acme_dns cloudflare {$CLOUDFLARE_DNS_API_TOKEN} dynamic_dns { - provider cloudflare {env.CLOUDFLARE_API_TOKEN} + provider cloudflare {$CLOUDFLARE_DNS_API_TOKEN} + check_interval 30m + ttl 5m domains { - ${config.networking.domain} @ + ${homelabDomain} @ } dynamic_domains } ''; + }; - networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall = { + allowedTCPPorts = [ 80 443 ]; + allowedUDPPorts = [ 443 ]; + }; + } diff --git a/hosts/lithium/services/calibre-web.nix b/hosts/lithium/services/calibre-web.nix new file mode 100644 index 0000000..38cafb5 --- /dev/null +++ b/hosts/lithium/services/calibre-web.nix @@ -0,0 +1,53 @@ +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + #certDir = config.security.acme.certs."${homelabDomain}".directory; + svcDomain = "books.${homelabDomain}"; + svcHttpPort = config.services.calibre-web.listen.port; + web_data_dir = "calibre-web"; + # TODO: I want the actual media stored in the tank. + library_path = "/tank/media/library/books"; + #library_path = "/var/lib/calibre-library"; +in +{ + # TODO: This isn't the right place for this, but we need to guarantee that a + # media group exists. + users.users.calibre-web.extraGroups = [ "media" ]; + users.groups.media = {}; + + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy localhost:8883 + ''; + + # reverse_proxy :${toString svcHttpPort} + # encode { + # zstd + # gzip + # minimum_length 1024 + # } + # ''; + + # NOTE: Needs some manual setup in Web-UI and I ecountered issues connecting even with firewall enabled. + # The following command is what I used to forward the port: + # ssh -f -N -L localhost:8883:localhost:8883 jml@lithium + services.calibre-web = { + enable = true; + listen.port = 8883; + # NOTE: Don't need to open calibre-web port, it's served by reverse_proxy + openFirewall = true; # TODO: Temporarily opened to allow configuration from inside my network. + + user = "calibre-web"; + group = "calibre-web"; + + # Either absolute path or directory name under "/var/lib" + # /tank/media/library/books + dataDir = web_data_dir; + + options = { + enableBookUploading = true; + enableBookConversion = true; + # NOTE: If I don't already have an extant calibreLibrary, I need to leave this null or the app won't launch. + calibreLibrary = library_path; + }; + }; +} diff --git a/hosts/lithium/services/forgejo.nix b/hosts/lithium/services/forgejo.nix new file mode 100644 index 0000000..2f6377f --- /dev/null +++ b/hosts/lithium/services/forgejo.nix @@ -0,0 +1,145 @@ +{ config, pkgs, lib, ... }: +let + homelabDomain = config.networking.domain; + svcDomain = "git.${homelabDomain}"; + theme = pkgs.fetchzip { + url = "https://github.com/catppuccin/gitea/releases/download/v1.0.2/catppuccin-gitea.tar.gz"; + hash = "sha256-rZHLORwLUfIFcB6K9yhrzr+UwdPNQVSadsw6rg8Q7gs="; + stripRoot = false; + }; + svcHttpPort = config.services.forgejo.settings.server.HTTP_PORT; + assetsDir = "${config.services.forgejo.stateDir}/custom/public/assets"; +in +{ + # NOTE: Periodically come update the catpuccin theme. + # `-auto` will automatically switch between latte and mocha modes. + services.forgejo.settings.ui = { + DEFAULT_THEME = "catpuccin-teal-auto"; + THEMES = builtins.concatStringsSep "," ( + [ "auto" ] + ++ (map (name: lib.removePrefix "theme-" (lib.removeSuffix ".css" name)) ( + builtins.attrNames (builtins.readDir theme) + )) + ); + }; + + # TODO: Setup a PostgreSQL Server. + # Inspiration here: https://github.com/nyawox/arcanum/blob/4629dfba1bc6d4dd2f4cf45724df81289230b61a/nixos/servers/forgejo.nix#L64 + #sops-secrets.postgres-forgejo = { + #sopsFile = ../secrets/forgejo.yaml; + #}; + + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${toString svcHttpPort} + ''; + + services.forgejo = { + enable = true; + # database.type = "postgres"; + settings = { + default.APP_NAME = "GitGarage"; + server = { + DOMAIN = svcDomain; + ROOT_URL = "https://${svcDomain}"; + HTTP_PORT = 3000; + }; + # NOTE: Actions support is based on: https://github.com/nektos/act + #actions = { + #ENABLED = true; + #DEFAULT_ACTIONS_URL = "github"; + #}; + actions.ENABLED = false; + # NOTE: Registration is handled with kanidm. + # Registration button link is at /user/sign_up + service = { + REGISTER_EMAIL_CONFIRM = false; + DISABLE_REGISTRATION = false; + ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + SHOW_REGISTRATION_BUTTON = false; + REQUIRE_SIGNIN_VIEW = false; + # TODO: Consider setting up emails. + ENABLE_NOTIFY_MAIL = false; + }; + openid = { + ENABLE_OPENID_SIGNIN = true; + ENABLE_OPENID_SIGNUP = true; + WHITELISTED_URIS = "id.${homelabDomain}"; + }; + # TODO: Literally review all server settings, and link the forgejo documentation. + # Also perhaps include every setting here explicitly. + oauth2_client = { + REGISTER_EMAIL_CONFIRM = false; + ENABLE_AUTO_REGISTRATION = true; + ACCOUNT_LINKING = "login"; + USERNAME = "nickname"; + UPDATE_AVATAR = true; + OPENID_CONNECT_SCOPES = "openid email profile"; + }; + repository = { + DEFAULT_PRIVATE = "private"; + DEFAULT_BRANCH = "main"; + ENABLE_PUSH_CREATE_USER = true; + ENABLE_PUSH_CREATE_ORG = true; + }; + mailer.ENABLED = false; + }; + }; + + # TODO: Finish Configuring the kandim oauth for forgejo.... + services.kanidm.provision.systems.oauth2.forgejo = { + displayName = "forgejo"; + # TODO: Get this from Forgejo + # originUrl = "https://git.${homelabDomain}/user/oauth2/${homelabDomain}/callback"; + originUrl = "${config.services.forgejo.settings.server.ROOT_URL}/user/oauth2/kanidm/callback"; + originLanding = "https://git.${homelabDomain}/"; + #basicSecretFile = "TODO!SETME"; + scopeMaps."git.users" = [ + "openid" + "email" + "profile" + "groups" + ]; + # WARNING: PKCE is currently not supported by gitea/forgejo, + # see https://github.com/go-gitea/gitea/issues/21376 + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + claimMaps.groups = { + joinType = "array"; + valuesByGroup."git.admins" = [ "admin" ]; + }; + }; + + systemd.services.forgejo = { + preStart = + lib.mkAfter # bash + '' + echo "Installing Catppuccin Assets" + rm -rf ${assetsDir} + mkdir -p ${assetsDir} + ln -sf ${theme} ${assetsDir}/css + ''; + }; + + + #sops.secrets.forgejo-runner-token = {}; + #services.gitea-actions-runner = { + #package = pkgs.forgejo-runner; + #instances.default = { + #enable = true; + #name = "monolith"; + #url = "https://${serviceDomain}"; + #tokenFile = config.sops.secrets.forgejo-runner-token.path; + # NOTE: I don't want huge images if it can be avoided. + # https://nektosact.com/usage/runners.html + #labels = [ + #"ubuntu-latest:docker://node:16-bullseye-slim" + #"ubuntu-22.04:docker://node:16-bullseye-slim" + #]; + #}; + #}; + + # TODO: Consider automatically creating admin account and password... + # https://wiki.nixos.org/wiki/Forgejo#Ensure_users + # Might be necessary to generate a token for kanidm + sops.secrets."forgejo/admin-password".owner = "forgejo"; +} diff --git a/hosts/lithium/services/forgejo/actions-runner.nix b/hosts/lithium/services/forgejo/actions-runner.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/lithium/services/forgejo/default.nix b/hosts/lithium/services/forgejo/default.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/lithium/services/forgejo/forgejo.nix b/hosts/lithium/services/forgejo/forgejo.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/lithium/services/game_servers.nix b/hosts/lithium/services/game_servers.nix new file mode 100644 index 0000000..0cc2929 --- /dev/null +++ b/hosts/lithium/services/game_servers.nix @@ -0,0 +1,42 @@ +{ pkgs, ... }: +{ + # TODO + # systemd.services..serviceConfig.{MemoryMax,CPUQuota} + systemd.services.valheim-server = { + description = "Valheim dedicated server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + }; + + serviceConfig = { + Type = "simple"; + User = "valheim"; + Group = "valheim"; + ExecStart = "${pkgs.steamcmd}/bin/steamcmd +login anonymous +force_install_dir /home/valheim/server +app_update 896660 validate +exit && /home/valheim/server/valheim_server.x86_64"; + }; + + users.users.valheim = { + isSystemUser = true; + group = "valheim"; + home = "/home/valheim"; + }; + users.groups.valheim = {}; + + networking.firewall = { + allowedTCPPorts = [ 7777 2456 ]; + allowedUDPPorts = [ 7777 2457 ]; + }; + + services.restic.backups.gameservers = { + user = "root"; + # TODO: Pick a real backup directory. + repository = "/backup/gameservers"; + paths = [ + "/var/lib/terraria" + "/home/valheim/server" + ]; + timeConfig = { + OnCalendar = "daily"; + }; + }; +} diff --git a/hosts/lithium/services/home-assistant.nix b/hosts/lithium/services/home-assistant.nix new file mode 100644 index 0000000..ba87895 --- /dev/null +++ b/hosts/lithium/services/home-assistant.nix @@ -0,0 +1,7 @@ +{ config, pkgs, ... }: +{ + services.home-assistant = { + enable = true; + openFirewall = true; + }; +} diff --git a/hosts/lithium/services/immich.nix b/hosts/lithium/services/immich.nix new file mode 100644 index 0000000..6226ade --- /dev/null +++ b/hosts/lithium/services/immich.nix @@ -0,0 +1,87 @@ +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + svcDomain = "photos.${homelabDomain}"; + photoStorageDir = "/tank/shares/photos"; + svcPort = config.services.immich.port; + # https://docs.immich.app/install/config-file/ + jsonSettings = { + server.externalDomain = "https://${svcDomain}"; + oauth = { + enabled = true; + issuerUrl = "https://"; # TODO: the kanidm url? + clientId = "immich"; + clientSecret = config.sops.placeholder."immich/oauth2_client_secret"; + scope = "openid email profile"; + signingAlgorithm = "ES256"; + storageLabelClaim = "email"; + buttonText = "Login with Kanidm"; + autoLaunch = true; + mobileOverrideEnabled = true; + mobileRedirectUri = "https://${svcDomain}/api/oauth/mobile-redirect/"; + }; + }; +in +{ + + # NOTE: The following repo contains a highly mature immich setup on nixos. + # https://github.com/xinyangli/nixos-config/blob/a8b5bea68caea573801ccfdb8ceacb7a8f2b0190/machines/agate/services/immich.nix + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${toString svcPort} + ''; + + # NOTE: Primarily to contain DB_PASSWORD to make it possible to backup and restore the DB. + # sops.secrets.immich_env = { + # sopsFile = ../../secrets/immich.env; + # format = "dotenv"; + # mode = "0440"; + # owner = "immich"; + # group = "immich"; + # restartUnits = [ "immich.service" ]; + # }; + sops.secrets."immich/oauth2_client_secret" = { }; + sops.templates."immich.json" = { + mode = "0440"; + owner = config.services.immich.user; + group = config.services.immich.group; + content = builtins.toJSON jsonSettings; + }; + + users.users.immich = { + isSystemUser = true; + }; + users.groups.immich = {}; + systemd.tmpfiles.rules = [ + "d ${photoStorageDir} 0770 immich immich -" + ]; + + # TODO: Setup mTLS for external / non-tailscale VPN immich access. + # https://github.com/alangrainger/immich-public-proxy/blob/main/docs/securing-immich-with-mtls.md + # TODO: Consider immich-public-proxy for generating "share" links + # https://github.com/alangrainger/immich-public-proxy + services.immich = { + enable = true; + openFirewall = true; + port = 2283; # default + #secretsFile = config.sops.secrets.immich_env.path; + + # TODO: Build this directory with permissions for the immich user. + mediaLocation = "/tank/shares/photos"; + environment = { + IMMICH_CONFIG_FILE = config.sops.templates."immich.json".path; + }; + }; + + services.kanidm.provision.systems.oauth2.immich = { + displayName = "immich"; + originUrl = "https://${svcDomain}/oauth2/oidc/callback"; + originLanding = "https://${svcDomain}/"; + basicSecretFile = config.sops.secrets."immich/oauth2_client_secret".path; + scopeMaps."immich.users" = [ + "openid" + "email" + "profile" + ]; + preferShortUsername = true; + }; +} diff --git a/hosts/lithium/services/kanidm.nix b/hosts/lithium/services/kanidm.nix index b8b96de..a302749 100644 --- a/hosts/lithium/services/kanidm.nix +++ b/hosts/lithium/services/kanidm.nix @@ -1,33 +1,91 @@ -{ config, pkgs, lib, ... }: +{ inputs, config, pkgs, lib, ... }: let - svcDomain = "id.${config.networking.domain}"; - caddyCertsRoot = "${config.services.caddy.dataDir}/.local/share/caddy/certificates"; - caddyCertsDir = "${caddyCertsRoot}/acme-v02.api.letsencrypt.org-directory"; - certsDir = "/var/lib/kanidm/certs"; + homelabDomain = inputs.nixos-secrets.homelabDomain; + svcDomain = "id.${homelabDomain}"; + kanidmCertDir = "/var/lib/kanidm/certs"; + caddyCertStore = "${config.services.caddy.dataDir}/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${svcDomain}"; + #kcertloc = "${caddyCertsStore}/${svcDomain}/"; + certRenewalScript = pkgs.writeShellScript "copy-kanidm-cert-hook" '' + set -Eeuo pipefail + mkdir -p ${kanidmCertDir} + cp ${caddyCertStore}/${svcDomain}.crt ${kanidmCertDir}/cert.pem + cp ${caddyCertStore}/${svcDomain}.key ${kanidmCertDir}/key.pem + + chown kanidm:kanidm ${kanidmCertDir}/*.pem + + ${pkgs.systemd}/bin/systemctl restart kanidm.service + ''; + kanidmCertCopier = "kanidm-cert-copier"; in { + # NOTE: Domains are serious when they are the root of identity/authnz. + # Recommendation from Kanidm docs for "Maximum" security is to maintain + # Both `example.com` and `id.example-auth.com`, the latter for idm infra exclusively. + # I consider that to be untenable and even more risky. + # The next recommendation is to follow a pattern like so + # id.example.com + # australia.id.example.com + # id-test.example.com + # australia.id-test.example.com + + # Example of yoinking certs from caddy: # https://github.com/marcusramberg/nix-config/blob/e558914dd3705150511c5ef76278fc50bb4604f3/nixos/kanidm.nix#L3 # TODO: If possible, consider specifying the cert location here instead of the following kludge. services.caddy.virtualHosts."${svcDomain}".extraConfig = '' reverse_proxy :8443 { + header_up Host {host} + header_up X-Real-IP {http.request.header.CF-Connecting-IP} transport http { tls_server_name ${svcDomain} } } ''; - # NOTE: Attempted kludge due to caddy generating (and therefore owning the certs) + # NOTE: Cleanup old rules + # systemd.tmpfiles.rules = lib.filter(rule: ! (lib.strings.hasPrefix "C ${kanidmCertDir}" rule)) config.systemd.tmpfiles.rules; systemd.tmpfiles.rules = [ - "d ${certsDir} 0750 kanidm caddy -" - "C ${certsDir}/cert.pem - kanidm - - ${caddyCertsDir}/${svcDomain}/${svcDomain}.crt" - "C ${certsDir}/key.key - kanidm - - ${caddyCertsDir}/${svcDomain}/${svcDomain}.key" + "d ${kanidmCertDir} 0750 kanidm kanidm -" ]; - systemd.services.kanidm = { - after = [ "systemd-tmpfiles-setup.service" ]; - requires = [ "caddy.service" "systemd-tmpfiles-setup.service" ]; + # NOTE: Include automation for copying cert files on renewal. + # systemd.services.caddy.serviceConfig = { + # ExecStartPost = [ + # "${certRenewalScript}/bin/copy-kanidm-cert-hook" + # ]; + # ExecReload = [ + # "${pkgs.caddy}/bin/caddy reload --config ${config.services.caddy.configFile}" + # "${certRenewalScript}/bin/copy-kanidm-cert-hook" + # ]; + # }; + systemd.services.${kanidmCertCopier} = { + description = "Copy Caddy certificates for Kanidm"; + requires = [ "caddy.service" ]; + after = [ "caddy.service" ]; + + serviceConfig = { + Type = "oneshot"; + User = "root"; + ExecStart = "${certRenewalScript}"; + }; }; + # systemd.services.caddy.wantedBy = [ "multi-user.target" ]; + # systemd.services.caddy.wants = [ kanidmCertCopier ]; + systemd.services.caddy.reloadTriggers = [ kanidmCertCopier ]; + systemd.timers.kanidm-cert-copier-daily = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnBootSec = "5min"; + OnCalendar = "daily"; + Unit = kanidmCertCopier; + }; + }; + + + # systemd.services.kanidm = { + # after = [ kanidmCertCopier ]; + # requires = [ kanidmCertCopier ]; + # }; users.users.kanidm.extraGroups = [ "caddy" ]; @@ -43,6 +101,7 @@ in }; }; + services.kanidm = { package = pkgs.kanidmWithSecretProvisioning_1_7; enableServer = true; @@ -51,13 +110,16 @@ in # domain, origin, tls_chain, tls_key domain = svcDomain; origin = "https://${svcDomain}"; - tls_chain = "${certsDir}/cert.pem"; - tls_key = "${certsDir}/key.key"; + tls_chain = "${kanidmCertDir}/cert.pem"; + tls_key = "${kanidmCertDir}/key.pem"; + # tls_chain = "${caddyCertStore}/${svcDomain}.crt"; + # tls_key = "${caddyCertStore}/${svcDomain}.key"; # NOTE: Optional Settings + # TODO: Configure the rest of the binding properly, should be 363 and maybe 8443 ldapbindaddress = "127.0.0.1:3636"; # For Jellyfin LDAP integration. - # trust_x_forwarded_for = true; + #trust_x_forwarded_for = true; }; enableClient = true; @@ -74,6 +136,7 @@ in home_alias = "name"; }; + # TODO: Migrate the secrets from here to `nixos-secrets` # NOTE: There are manual steps required as root to allow a user to set # their own credentials, or to confiugre an account as posix. As-is this # module doesn't support provisioning a complete user /w credentials. @@ -82,7 +145,9 @@ in # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#onboarding-a-new-person--resetting-credentials provision = { enable = true; - autoRemove = false; + autoRemove = true; + acceptInvalidCerts = true; + adminPasswordFile = config.sops.secrets."kanidm/admin-password".path; idmAdminPasswordFile = config.sops.secrets."kanidm/idm-admin-password".path; @@ -98,6 +163,8 @@ in "git.users" "git.admins" "tv.users" + "immich.users" + "miniflux.users" ]; }; }; @@ -107,6 +174,8 @@ in "git.admins" = {}; "tv.users" = {}; "tv.admins" = {}; + "immich.users" = {}; + "miniflux.users" = {}; }; }; }; diff --git a/hosts/lithium/services/miniflux/default.nix b/hosts/lithium/services/miniflux/default.nix new file mode 100644 index 0000000..bd92af4 --- /dev/null +++ b/hosts/lithium/services/miniflux/default.nix @@ -0,0 +1,79 @@ +{ config, pkgs, ... }: +let + homelabDomain = config.networking.domain; + svcDomain = "feeds.${homelabDomain}"; + svcPort = "8081"; # Prevent a Conflict +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${svcPort} + ''; + # NOTE: Ensure the user exists ahead of trying to give secret permissions to that user. + users.users.miniflux = { + isSystemUser = true; + group = "miniflux"; + createHome = false; + }; + users.groups.miniflux = {}; + sops.secrets.miniflux_env = { + sopsFile = ../../secrets/miniflux_admin_credentials.env; + format = "dotenv"; + mode = "0440"; + owner = "miniflux"; + group = "miniflux"; + restartUnits = [ "miniflux.service" ]; + }; + sops.secrets."miniflux/oauth2_client_secret" = { + owner = "miniflux"; + group = "kanidm"; + mode = "0440"; + restartUnits = [ "miniflux.service" "kanidm.service" ]; + }; + #services.kanidm.provision = { + #groups = {}; + #systems.oauth2.miniflux = { + #displayName = "Miniflux Feed Reader"; + #originUrl = "https://${fqdn}/callback"; + #public = true; # enforces PKCE + #preferShortUsername = true; + #scopeMaps.pages_users = ["openid" "email" "profile"]; + #claimMaps."${permissionsMap}".valuesByGroup.pages_admin = ["admin"]; + #}; + #}; + # NOTE: Currently requires some web-interface configuration + services.miniflux = { + enable = true; + adminCredentialsFile = config.sops.secrets.miniflux_env.path; + config = { + BASE_URL = "https://${svcDomain}"; + #CREATE_ADMIN = 0; + #DISABLE_LOCAL_AUTH = 1; + OAUTH2_PROVIDER = "oidc"; + OAUTH2_CLIENT_ID = "miniflux"; + OAUTH2_CLIENT_SECRET_FILE = config.sops.secrets."miniflux/oauth2_client_secret".path; + OAUTH2_REDIRECT_URL = "https://${svcDomain}/oauth2/oidc/callback"; + OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://id.${homelabDomain}/oauth2/openid/miniflux"; + #OAUTH2_USER_CREATION = 1; + CLEANUP_FREQUENCY = 48; + LISTEN_ADDR = "localhost:${svcPort}"; + }; + }; + + + services.kanidm.provision.systems.oauth2.miniflux = { + displayName = "miniflux"; + originUrl = "https://${svcDomain}/oauth2/oidc/callback"; + originLanding = "https://${svcDomain}/"; + basicSecretFile = config.sops.secrets."miniflux/oauth2_client_secret".path; + scopeMaps."miniflux.users" = [ + "openid" + "email" + "profile" + "groups" + ]; + # WARNING: PKCE is currently not supported by gitea/forgejo, + # see https://github.com/go-gitea/gitea/issues/21376 + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + }; +} diff --git a/hosts/lithium/services/monitoring/README.md b/hosts/lithium/services/monitoring/README.md new file mode 100644 index 0000000..93c1ca8 --- /dev/null +++ b/hosts/lithium/services/monitoring/README.md @@ -0,0 +1,14 @@ +# hosts/lithium/services/monitoring + +This is a Grafana/Prometheus Monitoring Stack. +Why? Basically for the sake of it. + +## Diagram + +```mermaid +```` + +## References + +- https://gist.github.com/rickhull/895b0cb38fdd537c1078a858cf15d63e +- https://xeiaso.net/blog/prometheus-grafana-loki-nixos-2020-11-20/ diff --git a/hosts/lithium/services/monitoring/default.nix b/hosts/lithium/services/monitoring/default.nix new file mode 100644 index 0000000..1e37aea --- /dev/null +++ b/hosts/lithium/services/monitoring/default.nix @@ -0,0 +1,6 @@ +{ ... }: { + imports = [ + ./grafana.nix + ./prometheus.nix + ]; +} diff --git a/hosts/lithium/services/monitoring/grafana.nix b/hosts/lithium/services/monitoring/grafana.nix new file mode 100644 index 0000000..afc986e --- /dev/null +++ b/hosts/lithium/services/monitoring/grafana.nix @@ -0,0 +1,26 @@ +{ inputs, config, pkgs, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + #svcDomain = "grafana.${config.networking.domain}"; + svcDomain = "grafana.${homelabDomain}"; + svcPort = config.services.grafana.settings.server.http_port; +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${toString svcPort} + ''; + + services.grafana = { + enable = true; + settings = { + server = { + http_addr = "127.0.0.1"; + http_port = 3001; + enforce_domain = true; + enable_gzip = true; + domain = svcDomain; + }; + analytics.reporting_enabled = false; # NOTE: Disable Telemetry + }; + }; +} diff --git a/hosts/lithium/services/monitoring/loki-local-config.yaml b/hosts/lithium/services/monitoring/loki-local-config.yaml new file mode 100644 index 0000000..919a718 --- /dev/null +++ b/hosts/lithium/services/monitoring/loki-local-config.yaml @@ -0,0 +1,4 @@ +auth_enabled: false + +server: + http_listen_port: 3100 diff --git a/hosts/lithium/services/monitoring/loki.nix b/hosts/lithium/services/monitoring/loki.nix new file mode 100644 index 0000000..448cc37 --- /dev/null +++ b/hosts/lithium/services/monitoring/loki.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + services.loki = { + enable = true; + #configFile = "./loki-local-config.yaml"; + # Nix Object representing the data that might otherwise be in a YAML config + # https://github.com/grafana/loki/blob/main/cmd/loki/loki-local-config.yaml + configuration = { + auth_enabled = false; + server = { + + }; + }; + }; +} diff --git a/hosts/lithium/services/monitoring/prometheus.nix b/hosts/lithium/services/monitoring/prometheus.nix new file mode 100644 index 0000000..84d818c --- /dev/null +++ b/hosts/lithium/services/monitoring/prometheus.nix @@ -0,0 +1,36 @@ +{ config, pkgs, ... }: +let + #svcDomain = "status.${config.networking.domain}"; + svcPort = config.services.prometheus.exporters.node.port; +in +{ + #services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + #reverse_proxy :${svcPort} + #''; + + services.prometheus = { + enable = true; + port = 9090; + #globalConfig.scrape_interval = "10s"; # "1m" + + exporters = { + # Export data about this host + node = { + enable = true; + enabledCollectors = [ "systemd" ]; + port = 9091; + }; + }; + + # Read data from the export + scrapeConfigs = [ + { + job_name = "node-lithium"; + static_configs = [{ + targets = [ "localhost:${toString svcPort}" ]; + }]; + } + ]; + }; + +} diff --git a/hosts/lithium/services/old-kanidm.nix b/hosts/lithium/services/old-kanidm.nix new file mode 100644 index 0000000..0bce514 --- /dev/null +++ b/hosts/lithium/services/old-kanidm.nix @@ -0,0 +1,79 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.services.kanidm; + authDomain = "auth.${config.networking.domain}"; + certsDir = config.security.acme.certs."${authDomain}".directory; +in +{ + # TODO: Pull in the appropriate sops-nix secrets and get this baby rolling. + # https://github.com/search?q=language%3ANix+services.kanidm&type=code + services.kanidm = { + # NOTE: Pin a specific kanidm version, we don't want issues from auto-updating. + package = pkgs.kanidm_1_6; + enableServer = true; + + # TODO: Initial kanidm setup. + # I sort of want users to be able to create their own accounts and what I + # don't want is for any of their account information to be leaked here as + # it can be used for remote logins. + # So kanidm accounts aside from the administration will be "impure". + # I vastly prefer people being able to set their own credentials: + # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#onboarding-a-new-person--resetting-credentials + provision = { + enable = true; + autoRemove = false; + # TODO: Add secrets from `sops-nix`. + adminPasswordFile = "TODO!SETME"; + idmAdminPasswordFile = "TODO!SETME"; + + persons = { + # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#resetting-person-account-credentials + # Needs to be a member of idm_people_admins and idm_high_privilege to prevent idm_service_desk from tampering. + zenware = { + displayName = "zenware"; + legalName = "zenware"; + mailAddresses = [ "zenware@${config.networking.domain} "]; + groups = [ + "idm_high_privilege" + "git.users" + "git.admins" + ]; + }; + # TODO: Make an idm_service_desk account. + }; + groups = { + # This group is `git` because it could be forgejo, gitea, etc. + "git.users" = {}; + "git.admins" = {}; + }; + systems.oauth2 = { + forgejo = { + displayName = "forgejo"; + originUrl = "TODO!SETME"; + originLanding = "TODO!SETME"; + basicSecretFile = "TODO!SETME"; + scopeMaps."git.users" = [ + "openid" + "email" + "profile" + ]; + # WARNING: PKCE is currently not supported by gitea/forgejo, + # see https://github.com/go-gitea/gitea/issues/21376 + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + claimMaps.groups = { + joinType = "array"; + valuesByGroup."git.admins" = [ "admin" ]; + }; + }; + }; + }; + + #enableClient = false; + clientSettings = { + uri = "https://${authDomain}"; + verify_hostnames = true; + verify_ca = true; + }; + }; +} diff --git a/hosts/lithium/services/palworld/PalWorldSettings.ini b/hosts/lithium/services/palworld/PalWorldSettings.ini new file mode 100755 index 0000000..d589452 --- /dev/null +++ b/hosts/lithium/services/palworld/PalWorldSettings.ini @@ -0,0 +1,2 @@ +[/Script/Pal.PalGameWorldSettings] +OptionSettings=(Difficulty=None,RandomizerType=None,RandomizerSeed="",bIsRandomizerPalLevelRandom=False,DayTimeSpeedRate=1.000000,NightTimeSpeedRate=1.000000,ExpRate=1.000000,PalCaptureRate=1.100000,PalSpawnNumRate=1.100000,PalDamageRateAttack=1.000000,PalDamageRateDefense=1.000000,PlayerDamageRateAttack=1.000000,PlayerDamageRateDefense=1.000000,PlayerStomachDecreaceRate=0.800000,PlayerStaminaDecreaceRate=0.900000,PlayerAutoHPRegeneRate=1.100000,PlayerAutoHpRegeneRateInSleep=1.200000,PalStomachDecreaceRate=0.900000,PalStaminaDecreaceRate=1.000000,PalAutoHPRegeneRate=1.000000,PalAutoHpRegeneRateInSleep=1.000000,BuildObjectHpRate=1.000000,BuildObjectDamageRate=1.000000,BuildObjectDeteriorationDamageRate=1.000000,CollectionDropRate=1.000000,CollectionObjectHpRate=1.000000,CollectionObjectRespawnSpeedRate=1.000000,EnemyDropItemRate=1.000000,DeathPenalty=1,bEnablePlayerToPlayerDamage=False,bEnableFriendlyFire=False,bEnableInvaderEnemy=True,bActiveUNKO=False,bEnableAimAssistPad=True,bEnableAimAssistKeyboard=True,DropItemMaxNum=3000,DropItemMaxNum_UNKO=100,BaseCampMaxNum=128,BaseCampWorkerMaxNum=15,DropItemAliveMaxHours=1.000000,bAutoResetGuildNoOnlinePlayers=False,AutoResetGuildTimeNoOnlinePlayers=72.000000,GuildPlayerMaxNum=20,BaseCampMaxNumInGuild=4,PalEggDefaultHatchingTime=4.500000,WorkSpeedRate=1.100000,AutoSaveSpan=30.000000,bIsMultiplay=False,bIsPvP=False,bHardcore=False,bPalLost=False,bCharacterRecreateInHardcore=False,bCanPickupOtherGuildDeathPenaltyDrop=False,bEnableNonLoginPenalty=True,bEnableFastTravel=True,bIsStartLocationSelectByMap=True,bExistPlayerAfterLogout=False,bEnableDefenseOtherGuildPlayer=False,bInvisibleOtherGuildBaseCampAreaFX=False,bBuildAreaLimit=False,ItemWeightRate=1.000000,CoopPlayerMaxNum=4,ServerPlayerMaxNum=32,ServerName="GameNight Pals",ServerDescription="",AdminPassword="PenQueen",ServerPassword="penking",PublicPort=8211,PublicIP="",RCONEnabled=False,RCONPort=25575,Region="",bUseAuth=True,BanListURL="https://api.palworldgame.com/api/banlist.txt",RESTAPIEnabled=False,RESTAPIPort=8212,bShowPlayerList=False,ChatPostLimitPerMinute=30,CrossplayPlatforms=(Steam,Xbox,PS5,Mac),bIsUseBackupSaveData=True,LogFormatType=Text,SupplyDropSpan=90,EnablePredatorBossPal=True,MaxBuildingLimitNum=0,ServerReplicatePawnCullDistance=15000.000000,bAllowGlobalPalboxExport=True,bAllowGlobalPalboxImport=False,EquipmentDurabilityDamageRate=1.000000,ItemContainerForceMarkDirtyInterval=1.000000) diff --git a/hosts/lithium/services/palworld/default.nix b/hosts/lithium/services/palworld/default.nix new file mode 100644 index 0000000..29a70f7 --- /dev/null +++ b/hosts/lithium/services/palworld/default.nix @@ -0,0 +1,53 @@ +{ config, pkgs, lib, ... }: +let + palworldSettings = builtins.readFile ./PalWorldSettings.ini; +in +{ + # NOTE: Partly inspired by: https://github.com/pocketpairjp/palworld-dedicated-server-docker + networking.firewall.allowedUDPPorts = [ 8211 ]; + + users.users.palworld = { + isSystemUser = true; + createHome = true; + home = "/home/palworld"; + homeMode = "750"; + group = "palworld"; + extraGroups = [ "steamcmd" ]; + }; + users.groups.palworld = {}; + + systemd.services.palworld = { + enable = true; + description = "PalWorld Dedicated Server"; + #after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStartPre = '' + ${pkgs.steamcmd}/bin/steamcmd +login anonymous \ + +app_update 2394010 validate +quit + ''; + ExecStart = '' + ${pkgs.steam-run}/bin/steam-run \ + .steam/steam/Steamapps/common/PalServer/PalServer.sh -publiclobby \ + -useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS + ''; + WorkingDirectory = "/home/palworld"; + Restart = "always"; + RuntimeMaxSec = "1d"; # NOTE: This thing has memory leaks, restart to save our selves. + User = "palworld"; + }; + }; + + # NOTE: Config is stashed at the following directory. + # /home/palworld/.steam/steam/Steamapps/common/PalServer/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini + # TODO: There are benefits to including the meat of the configuration inside the 'nix' file. + # Namely that it will result in actually updating the config when I rebuild. + environment.etc."palworld/PalWorldSettings.ini" = { + target = "/home/palworld/.steam/steam/Steamapps/common/PalServer/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini"; + text = palworldSettings; + mode = "0644"; + user = "palworld"; + group = "palworld"; + }; +} diff --git a/hosts/lithium/services/smartd.nix b/hosts/lithium/services/smartd.nix new file mode 100644 index 0000000..69999db --- /dev/null +++ b/hosts/lithium/services/smartd.nix @@ -0,0 +1,39 @@ +{ config, ... }: +{ + services.smartd = { + enable = true; + devices = [ + { + device = "/dev/disk/by-id/ata-CT500MX500SSD1_2206E607D6AA"; + } + { + device = "/dev/disk/by-id/ata-CT500MX500SSD1_2206E607D728"; + } + { + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL2B73HT"; + } + { + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL2PSELL"; + } + { + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL2B4RSM"; + } + { + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL23XYMM"; + } + { + device = "/dev/disk/by-id/nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244331X"; + } + { + device = "/dev/disk/by-id/nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244303V"; + } + ]; + }; + + services.prometheus.exporters.smartctl = { + enable = config.services.smartd.enable; + openFirewall = config.services.smartd.enable; + # https://github.com/prometheus-community/smartctl_exporter?tab=readme-ov-file#why-is-root-required-cant-i-add-a-user-to-the-disk-group + user = "root"; + }; +} diff --git a/hosts/lithium/services/uptime-kuma.nix b/hosts/lithium/services/uptime-kuma.nix index c9669eb..096beb1 100644 --- a/hosts/lithium/services/uptime-kuma.nix +++ b/hosts/lithium/services/uptime-kuma.nix @@ -13,6 +13,8 @@ in enable = true; # NOTE: NixOS Attributes here resolve into these ENV vars: # https://github.com/louislam/uptime-kuma/wiki/Environment-Variables - # settings = {}; + settings = { + PORT = "4000"; + }; }; } diff --git a/hosts/lithium/sops.nix b/hosts/lithium/sops.nix new file mode 100644 index 0000000..ce45efa --- /dev/null +++ b/hosts/lithium/sops.nix @@ -0,0 +1,15 @@ +{ inputs, ... }: +let + secretsPath = builtins.toString inputs.nixos-secrets; +in +{ + #imports = [ inputs.sops-nix.nixosModules.sops ]; + + sops = { + #defaultSopsFile = "${secretsPath}/${config.hostname}/secrets.yaml"; + #defaultSopsFile = "${secretsPath}/global/secrets.yaml"; + # TODO: Make this test the hostname. + #defaultSopsFile = "${secretsPath}/lithium/secrets/common.yaml"; + defaultSopsFile = "${secretsPath}/lithium/secrets.yaml"; + }; +} diff --git a/hosts/neon/boot.nix b/hosts/neon/boot.nix deleted file mode 100644 index e1f16ff..0000000 --- a/hosts/neon/boot.nix +++ /dev/null @@ -1,6 +0,0 @@ -{}: -{ - # Default to systemd-boot - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; -} \ No newline at end of file diff --git a/hosts/neon/default.nix b/hosts/neon/default.nix index 231f6da..6d3d3e0 100644 --- a/hosts/neon/default.nix +++ b/hosts/neon/default.nix @@ -1,10 +1,9 @@ { inputs, ... }: { imports = [ - ./boot.nix ../../modules/nixos/base.nix ../../modules/nixos/audio.nix - ../../modules/nixos/desktop + ../../modules/nixos/desktop.nix # https://github.com/NixOS/nixos-hardware/blob/master/README.md#using-nix-flakes-support inputs.nixos-hardware.nixosModules.gpd-pocket-3 # override from nixos-hardware diff --git a/hosts/titanium/README.md b/hosts/titanium/README.md deleted file mode 100644 index 51e0057..0000000 --- a/hosts/titanium/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# titanium - -This is my primary workstation / gaming pc. -It will generally be the most out of sync with the repo, as there will be a lot -of software I experiment with, which I simply forget to commit here. Everything -of importance will find it's way to this repo. - -## Non-Deterministic Post-Install Steps - -Rearrange Monitors in Gnome Display Settings - -Use a fido2 key (YubiKey) to decrypt luks -```bash -sudo -E -s systemd-cryptenroll --fido2-device=auto /dev/disk/by-partlabel/disk-main-luks -``` - -## Installing Remotely -```bash -nix run github:nix-community/nixos-anywhere -- --flake .#titanium -``` diff --git a/hosts/titanium/configuration.nix b/hosts/titanium/configuration.nix index 45987c6..c791efd 100644 --- a/hosts/titanium/configuration.nix +++ b/hosts/titanium/configuration.nix @@ -6,18 +6,18 @@ environment.systemPackages = with pkgs; [ sbctl # Secure-Boot helix nil # nice for editing '.nix' - (discord.override { withVencord = true; }) + discord signal-desktop obs-studio - halloy # IRC - gimp3 - nyxt # browser ]; + services.udev.extraRules = '' + SUBSYSTEM=="usb", ATTRS{idVendor}=="14ed", ATTRS{idProduct}=="1012", MODE="0666", GROUP="audio" + ''; # Hardware Specific programs... #programs.ryzen-monitor-ng.enable = true; #programs.rog-control-center.enable = true; services.openssh.enable = true; services.tailscale.enable = true; networking.firewall.trustedInterfaces = [ "tailscale0" ]; - system.stateVersion = "25.11"; + system.stateVersion = "25.05"; } diff --git a/hosts/titanium/default.nix b/hosts/titanium/default.nix index 8cece0c..bdc3d2f 100644 --- a/hosts/titanium/default.nix +++ b/hosts/titanium/default.nix @@ -1,41 +1,17 @@ -{ inputs, pkgs, ... }: -let - nixpkgs = inputs.nixpkgs; -in +{ inputs, ... }: { nixpkgs.config.allowUnfree = true; - nixpkgs.overlays = (import (../../overlays) {inherit nixpkgs;}); imports = [ ../../modules/nixos/base.nix ../../modules/nixos/audio.nix - ../../modules/nixos/desktop + ../../modules/nixos/desktop.nix ../../modules/nixos/gaming.nix inputs.nixos-hardware.nixosModules.asus-rog-strix-x570e ./hardware.nix ./configuration.nix ./nvidia.nix - inputs.lanzaboote.nixosModules.lanzaboote ./secure-boot.nix - inputs.disko.nixosModules.disko - ./disko.nix - ./game-emulation.nix - #./meetings.nix + #inputs.disko.nixosModules.disko + #./disko.nix ]; - - zw.gaming.enable = true; - - stylix = { - #enable = true; - # catppuccin-mocha - base16Scheme = "${pkgs.base16-schemes}/share/themes/catppuccin-mocha.yaml"; - # image = ./path.png; polarity = "dark"; # /etc/stylix/palette.html - # TODO: Add Atkinson Hyperlegible Next, Mono, and also a good Serif font. - # https://search.nixos.org/packages?channel=unstable&show=atkinson-hyperlegible-next&query=atkinson - # fonts = { - # serif = {}; - # sansSerif = {}; - # monospace = {}; - # emoji = {}; - # }; - }; } diff --git a/hosts/titanium/game-emulation.nix b/hosts/titanium/game-emulation.nix deleted file mode 100644 index e0ba3d2..0000000 --- a/hosts/titanium/game-emulation.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ config, lib, pkgs, ... }: -let - retroarchWithCores = ( - pkgs.retroarch.withCores ( - cores: with cores; [ - # Multi-Emulators - mame # Atari / Nintendo / Sega / etc. - - # Sega - genesis-plus-gx # Sega Genesis - - # Nintendo - mesen # NES - bsnes # Super Nintendo - mupen64plus # Nintendo 64 - Maybe simple64 some day. - dolphin # GameCube - mgba # GameBoy / Color / Advance - #melonds # Nintendo DS - #citra # Nintendo 3DS - - - # Sony - swanstation #duckstation # PlayStation - beetle-psx-hw - pcsx2 # PlayStation 2 -- Is actually "LRPS2" - #rpcs3 # PlayStation 3 - ppsspp # PlayStation Portable - - # Commodore - vice-x64 # C64 - ] - ) - ); -in -{ - environment.systemPackages = [ - retroarchWithCores - #pkgs.retroarch-full - #pkgs.emulationstation-de - pkgs.gnome-bluetooth - ]; - - hardware.xone.enable = true; # Xbox Controller Driver - hardware.xpadneo.enable = true; # Xbox Controller Driver - hardware.enableAllFirmware = true; - hardware.bluetooth = { - enable = true; - powerOnBoot = true; - settings = { - General = { - Experimental = true; - FastConnectable = true; - }; - Policy = { - AutoEnable = true; - }; - }; - }; -} diff --git a/hosts/titanium/hardware.nix b/hosts/titanium/hardware.nix index a11bb78..a2a8362 100644 --- a/hosts/titanium/hardware.nix +++ b/hosts/titanium/hardware.nix @@ -8,44 +8,41 @@ [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.systemd.enable = true; - #boot.initrd.luks.devices.FOO.crypttabExtraOpts = ["fido2-device=auto"]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-amd" ]; - # boot.blacklistedKernelModules = [ "nouveau" ]; boot.extraModulePackages = [ ]; fileSystems."/" = - { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; + { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; fsType = "btrfs"; options = [ "subvol=root" ]; }; - #boot.initrd.luks.devices."crypted".device = "/dev/disk/by-uuid/16b8ccb6-0102-4348-bb1b-d8d68bfb4d23"; - - fileSystems."/nix" = - { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; - fsType = "btrfs"; - options = [ "subvol=nix" ]; - }; + boot.initrd.luks.devices."crypted".device = "/dev/disk/by-uuid/0ccc4028-c27e-4259-ade9-a2b2081722cb"; fileSystems."/.swapvol" = - { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; + { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; fsType = "btrfs"; options = [ "subvol=swap" ]; }; + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/219D-4579"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + fileSystems."/home" = - { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; + { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; fsType = "btrfs"; options = [ "subvol=home" ]; }; - fileSystems."/boot" = - { #device = "/dev/disk/by-uuid/E076-75D6"; - fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; + fileSystems."/nix" = + { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; + fsType = "btrfs"; + options = [ "subvol=nix" ]; }; swapDevices = [ ]; @@ -57,7 +54,7 @@ networking.useDHCP = lib.mkDefault true; # networking.interfaces.enp4s0.useDHCP = lib.mkDefault true; # networking.interfaces.enp5s0.useDHCP = lib.mkDefault true; - # networking.interfaces.tailscale0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; diff --git a/hosts/titanium/meetings.nix b/hosts/titanium/meetings.nix deleted file mode 100644 index ed827ec..0000000 --- a/hosts/titanium/meetings.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ ... }: -{ - programs.zoom-us.enable = true; -} diff --git a/hosts/titanium/nvidia.nix b/hosts/titanium/nvidia.nix index af7717f..66b3fa2 100644 --- a/hosts/titanium/nvidia.nix +++ b/hosts/titanium/nvidia.nix @@ -14,12 +14,9 @@ # https://github.com/NixOS/nixpkgs/blob/master/pkgs/os-specific/linux/nvidia-x11/generic.nix#L65 nixpkgs.config.nvidia.acceptLicense = true; hardware.nvidia = { - # TODO: Consider legacy drivers. - # https://discourse.nixos.org/t/cant-use-nvidia-offload-mode/27791/8 package = config.boot.kernelPackages.nvidiaPackages.latest; modesetting.enable = true; - # Open Source Drivers: https://github.com/NVIDIA/open-gpu-kernel-modules#compatible-gpus - open = false; + open = true; nvidiaSettings = true; powerManagement.enable = false; powerManagement.finegrained = false; diff --git a/hosts/titanium/secure-boot.nix b/hosts/titanium/secure-boot.nix index be6cc79..82f4d98 100644 --- a/hosts/titanium/secure-boot.nix +++ b/hosts/titanium/secure-boot.nix @@ -1,4 +1,5 @@ -{ pkgs, lib, ... }: { +{ pkgs, lib, inputs, ... }: { + imports = with inputs; [ lanzaboote.nixosModules.lanzaboote ]; environment.systemPackages = [ pkgs.sbctl ]; boot.loader.systemd-boot.enable = lib.mkForce false; boot.lanzaboote.enable = true; diff --git a/lib/default.nix b/lib/default.nix index f3d2ac9..db5a123 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,113 +1,48 @@ +{ nixpkgs, home-manager, inputs, ... }: { - nixpkgs, - home-manager, - inputs, - ... -}: -let - allOverlays = import (../overlays) { inherit nixpkgs; }; - getPkgs = - system: - import nixpkgs { - inherit system; - overlays = allOverlays; - }; -in -{ - mkSystem = - { - hostname, - system ? "x86_64-linux", - users ? [ ], - extraModules ? [ ], - homeUsers ? { }, - extraSpecialArgs ? { }, - }: - let - pkgs_with_overlays = import nixpkgs { - inherit system; - overlays = allOverlays; - }; - hostModule = import ../hosts/${hostname} { - inherit inputs; - pkgs = pkgs_with_overlays; - }; - userModules = map ( - name: - import ../users/${name} { - pkgs = pkgs_with_overlays; - lib = nixpkgs.lib; - } - ) users; + # It's not really that I care about whether a system is a desktop system or + # a server system, but moreso that I care about whether a system is headless or not. + # I also care about things like if it's darwin, or wsl. + mkSystem = { + hostname, + system ? "x86_64-linux", + users ? [], + extraModules ? [] + }: + let + hostModule = import ../hosts/${hostname} { inherit inputs; }; + userModules = map (name: + import ../users/${name} { + pkgs = nixpkgs.legacyPackages.${system}; + lib = nixpkgs.lib; + } + ) users; - formattedHomeUsers = nixpkgs.lib.mapAttrs (username: moduleList: { - imports = moduleList; - }) homeUsers; - in + homeUserNames = builtins.filter (name: + builtins.pathExists ../users/${name}/home.nix + ) users; + + homeUsers = nixpkgs.lib.listToAttrs (map (name: { + name = name; + value = import ../users/${name}/home.nix { + username = name; + pkgs = nixpkgs.legacyPackages.${system}; + lib = nixpkgs.lib; + }; + }) homeUserNames); + in nixpkgs.lib.nixosSystem { inherit system; - modules = [ - hostModule - ] - ++ userModules - ++ extraModules - ++ ( - if homeUsers != { } then - [ - home-manager.nixosModules.home-manager - { - #home-manager.useGlobalPkgs = true; # NOTE: Incompatible with nixpkgs.{config,overlays} - home-manager.useUserPackages = true; - home-manager.backupFileExtension = "hm-bak"; - - # Directly inject the module lists? (isn't this the problem?) - home-manager.users = formattedHomeUsers; - home-manager.extraSpecialArgs = { inherit inputs; }; - } - ] - else - [ ] - ); - specialArgs = { - inherit inputs hostname; - } - // extraSpecialArgs; + specialArgs = { inherit inputs hostname; }; + modules = [ hostModule ] + ++ userModules + ++ extraModules + ++ (if homeUserNames != [] then [ + home-manager.nixosModules.home-manager + { + home-manager.backupFileExtension = "hm-bak"; + home-manager.users = homeUsers; + } + ] else []); }; - - getUserHomeModule = - username: pkgs: inputs: - import ../users/${username}/home.nix { - inherit username pkgs inputs; - lib = nixpkgs.lib; - }; - - /** - This function returns an attribute set { module, config }. - */ - mkHome = - { - username, - system ? "x86_64-linux", - extraModules ? [ ], - }: - let - pkgs_with_overlays = getPkgs system; - moduleList = [ - (import ../users/${username}/home.nix { - inherit inputs username; - pkgs = pkgs_with_overlays; - lib = nixpkgs.lib; - }) - ] - ++ extraModules; - in - { - module = moduleList; - config = home-manager.lib.homeManagerConfiguration { - pkgs = pkgs_with_overlays; - modules = moduleList; - }; - }; - - mkHomeConfigs = userProfiles: nixpkgs.lib.mapAttrs (username: profile: profile.config) userProfiles; } diff --git a/localnotes.md b/localnotes.md new file mode 100644 index 0000000..13756cd --- /dev/null +++ b/localnotes.md @@ -0,0 +1,37 @@ + + +Run disko first, then install. + +```bash +sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko -- --mode disko /path/to/disko.nix +sudo nixos-install --root /mnt --no-root-passwd --flake .#titanium +``` + +need to comment out lanzaboote stuff to get it working... :( +then re-enable it after the system is online again. + + +There is clearly some kind of quirk about boot drives. +We're going to try again, and double-check reading through config this time. + +I've already partitioned the drive(s) with disko, but I don't have a reason not to do it again. + +There is some reason why if I import disko into my nixos config it creates a conflict between the name of the drives. + +```bash +/dev/crypt/mapper +# and a full uuid path +``` + +I figured it out, after you have the disk paths and stuff setup with `disko` you no longer need to maintain them in `hardware-configuration.nix` +Which.. is actually quite nice to be honest. + + + +## Some Ideas to consider + +- https://github.com/Sveske-Juice/declarative-jellyfin +- https://docs.clan.lol +- fido2 luks cryptenroll + - https://discourse.nixos.org/t/using-fido2-luks-with-yubikey-pin/15484 +- https://github.com/nix-community/nixhelm/ diff --git a/localsecrets.yaml b/localsecrets.yaml new file mode 100644 index 0000000..ec09dc6 --- /dev/null +++ b/localsecrets.yaml @@ -0,0 +1,24 @@ +cloudflare_api_token: ENC[AES256_GCM,data:IqZ2LkBUyboO9494G3LPFn8prx48SDFluz6u4KDzQfQxTyqiVkORRQ==,iv:5iSnHMFHOEXDxt5/fSQ/83OzG2iU6LQ9OCnah5Qnj1A=,tag:zBQvE9KvW195mLtwjFKWqQ==,type:str] +cloudflare: + api_token: ENC[AES256_GCM,data:ZkiVQeVFHQ==,iv:402yjlUkamfzgAqMQCChR+ui4nsA625GidVIwCOc8bM=,tag:xErz+vXV8en2c3WdHfqUsg==,type:str] + email: ENC[AES256_GCM,data:AnI4i1ar70FvyLzVqiElJTbZ6V12Tw==,iv:VYoK2Q2XmleP2SV9Axy8JPTrPeLjnJBkhaXVuCWGUtA=,tag:uxB9JQJWUwoIQ1QtpbvT8Q==,type:str] +env: + domain_name: ENC[AES256_GCM,data:sGpnauqZ2LSY+Hf34eA=,iv:V1OOAo9zoEAkXDLL2la6DF+FoCj4Lzqg88dbHHSqcXs=,tag:C+0yaNo/TwAtym7NSxNnyA==,type:str] +yubico: + id: ENC[AES256_GCM,data:n80pw3A=,iv:pS/T3JGbVQkmYJ6EnwcdITe9J8knVBJiEn8njxPzAcM=,tag:gwg5pl6ugfBH4qwpcr1cjA==,type:int] + secret_key: ENC[AES256_GCM,data:kax8+XHJwpqFtRdKpkRR5sFhsKawlT7Ru92Umw==,iv:wSs4wdAkHyacKUmIxGfn8KDv1A8yW6E+0eBuXnOzhMA=,tag:Y6Om1OShD6s3dBALseN/qQ==,type:str] +tailscale: + auth_key: ENC[AES256_GCM,data:lIT80TrYfqMa8k6wsxC5BV6sBg6PCw5+AJaUtMhfJuXTIOz48PZKpCFq5z76TenpGpYT1vdqfCGd8Z1UfA==,iv:5LCWydaBX0ap5VScmjSm/QLtkeYy7u0ImVXoaY8URZs=,tag:dZV4s026eS4ME68ET+JxGw==,type:str] +vrising_server_name: ENC[AES256_GCM,data:guRSn4xsGFJ0,iv:spCO2OuFr2JmFL+qboq2dwrpxb7KufxtscZI8/3r9SQ=,tag:qbFV4IIiFmEQW72So6pm7A==,type:str] +valheim_server_name: ENC[AES256_GCM,data:PJV694YqSnOkBw==,iv:yIjgunzkiVdO1pUuAOtKcRI2zhBSb2sfDfM5WrPsVa8=,tag:I18ugPusdBoADlSxYzIYNw==,type:str] +kanidm: + bind_password: ENC[AES256_GCM,data:l9nP,iv:Qtk6hGj+RnLfsNBRp4QHpCo/Oxq+EdVu62xmClPbPNk=,tag:7PRHrMT5kJdtqV2xXZPzZg==,type:int] +tailscale: + auth_key: ENC[AES256_GCM,data:RFno,iv:wG8XyXMQt/BLjp3jW0j509cDmF/V+UqGAFCjJ3twQ3k=,tag:5z1krKBPDWlZGvHleS4rPA==,type:int] +gitea: + secret_key: ENC[AES256_GCM,data:u5EV,iv:UdQaFFC2Rh0aDbqzHdowhTmxrKbOhWEmGmUEjkOUrg4=,tag:MfB6Jbc3IPc8h4VAd4urEg==,type:int] + internal_token: ENC[AES256_GCM,data:K1tX,iv:MhM1IURTet1e919eI9NpitEdfG8WRB33E4GsCmcSDro=,tag:146dEI1/Bj+w5Ul+Sbt9bw==,type:int] + db_password: ENC[AES256_GCM,data:muy+,iv:e0drAD03om5xAmLOUa4IxTFHQ5U1xeK+fgDOhATnMU8=,tag:JVorF+C4+ENhFZ7/0QSwrQ==,type:int] + oauth_client_secret: ENC[AES256_GCM,data:hVM95DQxfS9Af/z+C5AgjpcoHBs=,iv:pq4lXNYXzFIaNUWhmCV5EwD4icjziCWVqpSuIg1FzZQ=,tag:z/lxukCKwgriNLqqeHDFuQ==,type:str] +jellyfin: + oauth_client_secret: ENC[AES256_GCM,data:IQI6FfOga+3bmf+B+/vpGao=,iv:lC/zbax5mgzQBRNIIbeviWBXtMKSegKFJlHdY+bCSyo=,tag:g0BUqfHZrJB2gJUIjLjnuA==,type:str] diff --git a/modules/nixos/base.nix b/modules/nixos/base.nix index d273887..036a5c9 100644 --- a/modules/nixos/base.nix +++ b/modules/nixos/base.nix @@ -1,23 +1,18 @@ { config, pkgs, lib, ... }: { nixpkgs.config.allowUnfree = true; - # TODO: Consider adding a randomized delay. - nix.gc = { - automatic = true; - dates = "weekly"; - options = "--delete-older-than 30d"; - }; nix.settings = { - auto-optimise-store = true; experimental-features = [ "nix-command" "flakes" ]; }; - # https://datatracker.ietf.org/doc/html/rfc8375 - networking.domain = lib.mkDefault "home.arpa"; + # Default to systemd-boot + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; - # TODO: Consider enabling automatic-timezoned on laptops that move between TZs - time.timeZone = lib.mkDefault "America/Chicago"; - services.automatic-timezoned.enable = lib.mkDefault false; + # https://datatracker.ietf.org/doc/html/rfc8375 + networking.domain = "home.arpa"; + + time.timeZone = "America/Chicago"; i18n.defaultLocale = "en_US.UTF-8"; i18n.extraLocaleSettings = { @@ -78,39 +73,38 @@ ]; # Render colors # TODO: Figure out how to represent those termcap sequences properly. - LESS_TERMCAP_mb="\E[1;31m"; # begin bold - LESS_TERMCAP_md="\E[1;36m"; # begin blink - LESS_TERMCAP_me="\E[0m"; # reset bold/blink - LESS_TERMCAP_so="\E[01;44;33m"; # begin reverse video - LESS_TERMCAP_se="\E[0m"; # reset reverse video - LESS_TERMCAP_us="\E[1;32m"; # begin underline - LESS_TERMCAP_ue="\E[0m"; # reset underline + #LESS_TERMCAP_mb=$'\E[1;31m' # begin bold + #LESS_TERMCAP_md=$'\E[1;36m' # begin blink + #LESS_TERMCAP_me=$'\E[0m' # reset bold/blink + #LESS_TERMCAP_so=$'\E[01;44;33m' # begin reverse video + #LESS_TERMCAP_se=$'\E[0m' # reset reverse video + #LESS_TERMCAP_us=$'\E[1;32m' # begin underline + #LESS_TERMCAP_ue=$'\E[0m' # reset underline }; }; git.enable = true; htop.enable = true; + command-not-found.enable = false; bat.enable = true; bandwhich.enable = true; - command-not-found.enable = false; - #nix-index.enable = true; - nano.enable = false; neovim = { enable = true; defaultEditor = true; + viAlias = true; vimAlias = true; + + withRuby = true; + withPython3 = true; + withNodeJs = true; + + #configure = {}; }; }; - services.openssh.enable = lib.mkDefault false; - # services.openssh = { - # enable = true; - # settings = { - # PasswordAuthentication = false; - # PermitRootLogin = "no"; - # }; - # }; + # Services running on all machines + services.avahi.enable = true; # zeroconf/mDNS(.local) } diff --git a/modules/nixos/desktop/default.nix b/modules/nixos/desktop.nix similarity index 67% rename from modules/nixos/desktop/default.nix rename to modules/nixos/desktop.nix index 6c76134..5e4a3c2 100644 --- a/modules/nixos/desktop/default.nix +++ b/modules/nixos/desktop.nix @@ -1,22 +1,11 @@ { pkgs, ... }: { - imports = [ - ./calibre.nix - ../fonts.nix - ]; - - # TODO: Add options for enabling/switching between different Desktop Environments. - # options = {}; - - # NOTE: Calibre is enabled this way because it also needs udisks2 for e-readers - # Ideally I move it somewhere else anyway. - zw.calibre.enable = true; - environment.systemPackages = with pkgs; [ yubikey-personalization xdg-desktop-portal-gtk xdg-desktop-portal-hyprland xwayland + #rofi-wayland rofi waybar hyprpaper @@ -43,5 +32,10 @@ }; # screen sharing /w hyp services.dbus.enable = true; - services.avahi.enable = true; # zeroconf/mDNS(.local) + + fonts.packages = with pkgs; [ + nerd-fonts.fira-code + nerd-fonts.iosevka + atkinson-hyperlegible + ]; } diff --git a/modules/nixos/desktop/calibre.nix b/modules/nixos/desktop/calibre.nix deleted file mode 100644 index 5fa97d5..0000000 --- a/modules/nixos/desktop/calibre.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ config, lib, pkgs, ... }: -{ - imports = []; - - options = { - zw.calibre = { - enable = lib.mkEnableOption "Enable Calibre"; - }; - }; - - config = { - # NOTE: Without unrar support we can't open ".cbr" files. - environment.systemPackages = with pkgs; [ - calibre - ]; - - services.udisks2.enable = true; # Required for eReader Support - }; - # NOTE: Consider adding https://github.com/nydragon/calibre-plugins - # especially for DeDRM -} diff --git a/modules/nixos/desktop/niri/default.nix b/modules/nixos/desktop/niri/default.nix deleted file mode 100644 index e239697..0000000 --- a/modules/nixos/desktop/niri/default.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ config, lib, pkgs, inputs, ... }: -{ - # Opinionated Niri Setup - https://yalter.github.io/niri/Important-Software.html - # Consider: https://github.com/sodiboo/niri-flake - - # NOTE: Rather than individual components, I'm going to start with a complete desktop shell if possible. - # According to the docs there's a few options: https://yalter.github.io/niri/Getting-Started.html#desktop-environments - # LXQt, many parts of XFCE, COSMIC + `cosmic-ext-extra-sessions` - # And what I actually want to try out is one of DankMaterialShell or Noctalia - programs.niri.enable = true; - - environment.systemPackages = with pkgs; [ - inputs.noctalia.packages.${system}.default - xwayland-satellite - fuzzel - kitty - fastfetch - ]; - - services.displayManager.sessionPackages = [ pkgs.niri ]; - programs.niri.package = pkgs.niri; - - - # Notification Daemon - #services.mako.enable = true; - #services.mako.settings.default-timeout = 3000; - - # Portal - https://wiki.archlinux.org/title/XDG_Desktop_Portal#List_of_backends_and_interfaces - - # Authentication Agent (polkit) - #security.polkit.enable = lib.mkDefault true; - - # Xwayland - # https://github.com/Supreeeme/xwayland-satellite - #programs.xwayland.enable = lib.mkDefault true; - - # Screencasting - https://yalter.github.io/niri/Screencasting.html - # Needs D-Bus, pipewire, `xdg-desktop-portal-gnome`? Or a portal from the above table with screencasting support - -} \ No newline at end of file diff --git a/modules/nixos/desktop/xfce/default.nix b/modules/nixos/desktop/xfce/default.nix deleted file mode 100644 index cae144b..0000000 --- a/modules/nixos/desktop/xfce/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{}: -{ - services.displayManager.defaultSession = "xfce"; - services.xserver.desktopManager = { - xterm.enable = false; - xfce.enable = true; - }; - -} \ No newline at end of file diff --git a/modules/nixos/fonts.nix b/modules/nixos/fonts.nix deleted file mode 100644 index 7d3eca8..0000000 --- a/modules/nixos/fonts.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ pkgs, ... }: -{ - fonts.packages = with pkgs; [ - nerd-fonts.fira-code - nerd-fonts.iosevka - atkinson-hyperlegible - ]; -} \ No newline at end of file diff --git a/modules/nixos/gaming.nix b/modules/nixos/gaming.nix index 1e86c7e..68b2946 100644 --- a/modules/nixos/gaming.nix +++ b/modules/nixos/gaming.nix @@ -1,31 +1,17 @@ { config, lib, pkgs, ... }: { - #imports = []; - options = { - zw.gaming.enable = lib.mkEnableOption "Enable Gaming"; - }; - - # https://wiki.nixos.org/wiki/Category:Gaming - config = lib.mkIf config.zw.gaming.enable { - environment.systemPackages = with pkgs; [ - mangohud - protonup-qt - lutris # TODO: Having an issue after flake update - bottles - heroic - ]; - programs.steam = { - enable = true; - remotePlay.openFirewall = true; - localNetworkGameTransfers.openFirewall = true; - protontricks.enable = true; - gamescopeSession.enable = true; - }; - - programs.gamemode.enable = true; - programs.gamescope = { - enable = true; - capSysNice = true; - }; + environment.systemPackages = with pkgs; [ + mangohud + protonup-qt + lutris + bottles + heroic + ]; + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + localNetworkGameTransfers.openFirewall = true; + protontricks.enable = true; + gamescopeSession.enable = true; }; } diff --git a/overlays/default.nix b/overlays/default.nix deleted file mode 100644 index f981c72..0000000 --- a/overlays/default.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ nixpkgs }: - let - fixCmake = pkg: pkg.overrideAttrs (old: { - cmakeFlakes = (old.cmakeFlags or []) ++ [ - (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") - ]; - }); - cmake3Overlay = final: prev: - nixpkgs.lib.mapAttrs ( - n: pkg: - pkg.overrideAttrs (old: { - cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; - }) - ) { - inherit (prev) hpipm; - }; - libretroCmake3Overlay = final: prev: { - libretro = prev.libretro // { - thepowdertoy = prev.libretro.thepowdertoy.overrideAttrs(old: { - cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; - }); - - tic80 = prev.libretro.tic80.overrideAttrs(old: { - cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; - }); - - citra = prev.libretro.citra.overrideAttrs(old: { - cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; - }); - - dolphin = prev.libretro.dolphin.overrideAttrs(old: { - cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; - }); - }; - }; -in -[ - cmake3Overlay - libretroCmake3Overlay -] diff --git a/pkgs/mv7-udev-rules/package.nix b/pkgs/mv7-udev-rules/package.nix new file mode 100644 index 0000000..32e03bb --- /dev/null +++ b/pkgs/mv7-udev-rules/package.nix @@ -0,0 +1,38 @@ +{ + lib, + stdenv, + fetchFromGitHub, +}: + +# Based on: +# https://github.com/NixOS/nixpkgs/blob/nixos-25.05/pkgs/by-name/zs/zsa-udev-rules/package.nix + +stdenv.mkDerivation { + pname = "mv7-udev-rules"; + version = "unstable-2025-06-20"; + + src = fetchFromGitHub { + owner = "zenware"; + repo = "mv7-udev-rules"; + rev = "000000000000000000000000000000000"; + hash = "sha256-0000000000000000000000000"; + }; + + # Only copy udev rules + dontConfigure = true; + dontBuild = true; + dontFixup = true; + + installPhase = '' + mkdir -p $out/lib/udev/rules.d + cp dist/linux64/99-mv7-mic.rules $out/lib/udev/rules.d/ + ''; + + meta = with lib; { + description = "udev rules for MV7 devices"; + license = licenses.mit; + maintainers = with maintainers; [ zenware ]; + platforms = platforms.linux; + homepage = "https://github.com/zenware/mv7-udev-rules"; + }; +} diff --git a/secrets/global.yaml b/secrets/global.yaml new file mode 100644 index 0000000..893df2b --- /dev/null +++ b/secrets/global.yaml @@ -0,0 +1,36 @@ +cloudflare_api_token: ENC[AES256_GCM,data:IqZ2LkBUyboO9494G3LPFn8prx48SDFluz6u4KDzQfQxTyqiVkORRQ==,iv:5iSnHMFHOEXDxt5/fSQ/83OzG2iU6LQ9OCnah5Qnj1A=,tag:zBQvE9KvW195mLtwjFKWqQ==,type:str] +kanidm: + bind_password: ENC[AES256_GCM,data:l9nP,iv:Qtk6hGj+RnLfsNBRp4QHpCo/Oxq+EdVu62xmClPbPNk=,tag:7PRHrMT5kJdtqV2xXZPzZg==,type:int] +tailscale: + auth_key: ENC[AES256_GCM,data:RFno,iv:wG8XyXMQt/BLjp3jW0j509cDmF/V+UqGAFCjJ3twQ3k=,tag:5z1krKBPDWlZGvHleS4rPA==,type:int] +gitea: + secret_key: ENC[AES256_GCM,data:u5EV,iv:UdQaFFC2Rh0aDbqzHdowhTmxrKbOhWEmGmUEjkOUrg4=,tag:MfB6Jbc3IPc8h4VAd4urEg==,type:int] + internal_token: ENC[AES256_GCM,data:K1tX,iv:MhM1IURTet1e919eI9NpitEdfG8WRB33E4GsCmcSDro=,tag:146dEI1/Bj+w5Ul+Sbt9bw==,type:int] + db_password: ENC[AES256_GCM,data:muy+,iv:e0drAD03om5xAmLOUa4IxTFHQ5U1xeK+fgDOhATnMU8=,tag:JVorF+C4+ENhFZ7/0QSwrQ==,type:int] + oauth_client_secret: ENC[AES256_GCM,data:hVM95DQxfS9Af/z+C5AgjpcoHBs=,iv:pq4lXNYXzFIaNUWhmCV5EwD4icjziCWVqpSuIg1FzZQ=,tag:z/lxukCKwgriNLqqeHDFuQ==,type:str] +jellyfin: + oauth_client_secret: ENC[AES256_GCM,data:IQI6FfOga+3bmf+B+/vpGao=,iv:lC/zbax5mgzQBRNIIbeviWBXtMKSegKFJlHdY+bCSyo=,tag:g0BUqfHZrJB2gJUIjLjnuA==,type:str] +sops: + age: + - recipient: age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuOTRKeDNjSEdnQ2ZRNnI3 + dzZJc0xJdFFOUk9tWDJRcHZZSXVUMkpRQUc0CjhGWkNYR1daR2VWT2JOQUFZVlJO + ZGswSU5vaDJLWm5INXp5MlVQYjBCUzQKLS0tIDlrZjN6SGFnNDY4TEN6NjlPN01Y + dGRsTVpBMGVaVytpTm55WEIzNVpHTDQK8p9yexr9L7TwBPu/jKZkdDD2GOt9+nkK + 6tcckBjVx/SUIs7U0qbE6DkzCXIWo2Ce5hsk4RE1p91Y4vocaMPxYA== + -----END AGE ENCRYPTED FILE----- + - recipient: age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyZUI5VFp5R1Z1SU5XSEtt + QndNajRsR0VyOTUrNjljcnlVRW8vRnVid1hjCmhraVA1anFEdUJoa0lMNm5RcjFE + b1o3bzBpRm83VVhWQy94NXNqSjJSekUKLS0tIGNaQno3RzEyYlNPT0RsNzEzaUd6 + c2tIcEx4VGpIVXZzcEJoUTRGRjdSTjAKk4C6PQiAZpunDmNitkrTBq6PqRe53mZB + ehF6fL7DTveVwWq02csekQdi7hXShkoH7EEMw1LrEe6IP7oJbvZ3jw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-06-04T13:43:02Z" + mac: ENC[AES256_GCM,data:Kd+9kPRgwfdJh9rMADopqJyocPg4M3hnvW8LYxV8jcoOGvuK+rBPu0rQF30ZGUq0i7LG7WiqN+m7nDTrl6KcO4WN4IyTqLJ/lheOLiBTpbUv68VEYPEbTEkvTMrfhsaCNk3AUuUI34cle+k9Q0/QgNenVx7yH77VzR3aiYH/hzA=,iv:s6+V8wTYTE6Q28Kyjb2NlyoGRvUaliaeJAn6htQ1Xwo=,tag:ZkO/mKZ/Dk1jit6qgTxzMA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/secrets/temp.yaml b/secrets/temp.yaml new file mode 100644 index 0000000..d6bf591 --- /dev/null +++ b/secrets/temp.yaml @@ -0,0 +1,56 @@ +#ENC[AES256_GCM,data:dqhy221XOImoFPMsVz3eFipnQZRxDvoXAWRW4gT/UKqmJrsZp/CgmISo/yx7d3Y+Otk2mZHPmi8=,iv:jPJ3jL7heD721vNnGveNUNdOOwJngCFFbaKHxQxwu1w=,tag:EX/SqAJa9H1KMUnJHvwBbw==,type:comment] +#ENC[AES256_GCM,data:2QAMIK1AD8iEVsBl/tEiWAAjjpMzjvnVpoIa8h60KSCEsU8nycqndOPCLq3BOJGK0a5qITm0,iv:HOJ0tFMEY+99aDXdWjiHLXhpssSEMuMhby/n2W/0HqA=,tag:bEZ+IruPQYNj8rJXn3kbvA==,type:comment] +cloudflare: + api_token: ENC[AES256_GCM,data:ZkiVQeVFHQ==,iv:402yjlUkamfzgAqMQCChR+ui4nsA625GidVIwCOc8bM=,tag:xErz+vXV8en2c3WdHfqUsg==,type:str] + email: ENC[AES256_GCM,data:AnI4i1ar70FvyLzVqiElJTbZ6V12Tw==,iv:VYoK2Q2XmleP2SV9Axy8JPTrPeLjnJBkhaXVuCWGUtA=,tag:uxB9JQJWUwoIQ1QtpbvT8Q==,type:str] +#ENC[AES256_GCM,data:qcSPXWftLd3ojT2kQrqsZFuIzRSk7otMj+DA945UYvrut1O6mjYrzKwf/IyHUmlaDFh7kenPXgGDwm5VU9w=,iv:wRGpS4aeMO9tpF4vHE6sKMt1LA9YcLW8+G7VBWwYMOo=,tag:VEDXurG64aT43pi0lKLN1w==,type:comment] +env: + domain_name: ENC[AES256_GCM,data:sGpnauqZ2LSY+Hf34eA=,iv:V1OOAo9zoEAkXDLL2la6DF+FoCj4Lzqg88dbHHSqcXs=,tag:C+0yaNo/TwAtym7NSxNnyA==,type:str] +#ENC[AES256_GCM,data:IYmlxtKW06u6orlQii4IfB45O88ofznUvuuzYt0=,iv:YdDbHxqG/Nd9CF9l/BBMEO28VYnTiKvkdXxTbMJjRG8=,tag:y0rADtZhmdYZjiax9YvJzg==,type:comment] +yubico: + id: ENC[AES256_GCM,data:n80pw3A=,iv:pS/T3JGbVQkmYJ6EnwcdITe9J8knVBJiEn8njxPzAcM=,tag:gwg5pl6ugfBH4qwpcr1cjA==,type:int] + secret_key: ENC[AES256_GCM,data:kax8+XHJwpqFtRdKpkRR5sFhsKawlT7Ru92Umw==,iv:wSs4wdAkHyacKUmIxGfn8KDv1A8yW6E+0eBuXnOzhMA=,tag:Y6Om1OShD6s3dBALseN/qQ==,type:str] +#ENC[AES256_GCM,data:Zwum1QmpeQUb4PIxdqY=,iv:stOFFRpaR+kHIfADKS/o//K1+oQ+Y9ANNp5LbrbgW9c=,tag:hUdnj2menajZhM7yuRs0aQ==,type:comment] +tailscale: + auth_key: ENC[AES256_GCM,data:lIT80TrYfqMa8k6wsxC5BV6sBg6PCw5+AJaUtMhfJuXTIOz48PZKpCFq5z76TenpGpYT1vdqfCGd8Z1UfA==,iv:5LCWydaBX0ap5VScmjSm/QLtkeYy7u0ImVXoaY8URZs=,tag:dZV4s026eS4ME68ET+JxGw==,type:str] +#ENC[AES256_GCM,data:TBtQO7kI+rfcy2XlpYCIAkviKS0=,iv:JjLLJqDMFmHtrqgIH9xVlJ6gbeFT7g74kFL8nZH+nCk=,tag:rUpKWnstKtqbJbGLk9dQfw==,type:comment] +vrising_server_name: ENC[AES256_GCM,data:guRSn4xsGFJ0,iv:spCO2OuFr2JmFL+qboq2dwrpxb7KufxtscZI8/3r9SQ=,tag:qbFV4IIiFmEQW72So6pm7A==,type:str] +valheim_server_name: ENC[AES256_GCM,data:PJV694YqSnOkBw==,iv:yIjgunzkiVdO1pUuAOtKcRI2zhBSb2sfDfM5WrPsVa8=,tag:I18ugPusdBoADlSxYzIYNw==,type:str] +example_key: ENC[AES256_GCM,data:RPKzGyhQVMt53UIrbg==,iv:WdJEIrcLjqwyaEiXAOGoGihp0tgr3P0j+coQThRSAqM=,tag:efPXuh06+ZEyRAY6M8O6Vg==,type:str] +#ENC[AES256_GCM,data:hwNzDeFecGqtr1gCdxQ2Dg==,iv:fvPKS3tH5i+HdJhGxJz7Bf0nM/DZDqGYFy23/CTQq14=,tag:ieLl2TJuIj0mPzAHlZeWKw==,type:comment] +example_array: + - ENC[AES256_GCM,data:Wh1JeEYh5XIXqxCi/kc=,iv:3MH0nBTXkYWSf2FTSJAelSR0jPHhsp0AEPH3bq1v6WM=,tag:pGs/aD013fzjgX1mzFWSeQ==,type:str] + - ENC[AES256_GCM,data:0mIilx8XdDOg5oRxcrA=,iv:Tm6E3M8hi3HqTxO/vFO3GVlZ8IgUKjAliYbHwh4SEqw=,tag:g9u7zaBENVdcloWpj6jxBg==,type:str] +example_number: ENC[AES256_GCM,data:5M+hN39uq5hn7A==,iv:vxWdPRafSZ4LYKgjDK8hrqwb7mMjLDxf7/mcb9Fe4r8=,tag:YmTtnwCcnX+xVs09XFLQfA==,type:float] +example_booleans: + - ENC[AES256_GCM,data:AtfqPA==,iv:/Hsubc6st3Htaidi634RAndd9Rl2Ldetzm+YfZ2Vu0o=,tag:TqC6nn7cAWffzuWk0e2tCw==,type:bool] + - ENC[AES256_GCM,data:nkbswos=,iv:FBM0yr8MdotAWwxyD6aHhYPjINDeJ5Yu3PRQAg6ey/8=,tag:oCgE9qJHRNLDboO80dOjgw==,type:bool] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5cGxrQkpqTGJiaGNtenVG + Y2JhVVpDenhuS050SU9hald0RlRRdGpIK3owCkxSNVAzTVNlbmNGSjNZRVlYb3E3 + RVM0ZUVmNkJDRW1NcFpzcjR3QndTaGcKLS0tIElUSCsyQmF1cW52UnVsQlZVT1E0 + OUNLVk1uNWJNbUNRS1d0Q3FIYXFTZGcKRRK5AO8fQ835zNUDoseBAMPEIxlmAxXT + kv82umpkOyAKQe4opDrxdaJQwoT4nYqdr26ZXCEhajNo1sit9j1z/g== + -----END AGE ENCRYPTED FILE----- + - recipient: age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmcUVsQU9MNHExd0QyWlZ2 + eVVFd1h4WXJyb0lERFFFbWlqQzFGUFJMT3lJCk1iNXRlVTJjaVBjNjB2LzRIcUdr + dk01QU1hbXZwSk50SXhyWlY3WTM4SEEKLS0tIE95eDEydkExVkU1RUNkVUh0TnU4 + cGpKVCt3dnVOcTYycDNGeVNFWTQvM28KNbvMhnu/kee2lvEqzTeg7708H+HwxSlD + hR4rWnf/lvA66DIFP7RQN0neouC3mD71irlhAYTWV9h3J9/0z/De1A== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-06-02T20:31:13Z" + mac: ENC[AES256_GCM,data:YaTn5x0jBvM9Yjj53IClYX11zIYZlrp95IbljXX3E5GJApTL4Mkigv1sPJXwq4jJ67JCQL3bdmLMyvWDfuLd1deVtG1LXD4NFYxFaeUXWgBfPs2IW3l/JakU6kliluZRwe5hwhCNIb/+7t9948HLq5MDIaLU2PDeASK/wySOYno=,iv:3D4o66NrUlxFagO80LSyei8BsKyb6dYN75eHs/MhOpw=,tag:3oNBSmZwGkv8MJduv4Sr8w==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.2 diff --git a/users/jay/default.nix b/users/jay/default.nix new file mode 100644 index 0000000..d91cd38 --- /dev/null +++ b/users/jay/default.nix @@ -0,0 +1,16 @@ +{ pkgs, lib, ... }: +{ + users.users.jay = { + home = + if pkgs.stdenv.isLinux then + lib.mkDefault "/home/jay" + else if pkgs.stdenv.isDarwin then + lib.mkDefault "/Users/jay" + else + abort "Unsupported OS"; + } // lib.optionalAttrs pkgs.stdenv.isLinux { + isNormalUser = true; + extraGroups = [ "networkmanager" "wheel" ]; + # hashedPassword = ""; + }; +} diff --git a/users/jay/home.nix b/users/jay/home.nix new file mode 100644 index 0000000..2b8f6d0 --- /dev/null +++ b/users/jay/home.nix @@ -0,0 +1,68 @@ +{ pkgs, lib, ... }: +{ + # NOTE: This file contains options that resolve under home-manager.users. + home.stateVersion = "25.05"; + + home.sessionVariables = { + EDITOR = "hx"; + }; + home = { + username = "jay"; + homeDirectory = + if pkgs.stdenv.isLinux then + lib.mkDefault "/home/jay" + else if pkgs.stdenv.isDarwin then + lib.mkDefault "/Users/jay" + else + abort "Unsupported OS"; + }; + home.packages = with pkgs; [ ] + # linux only + # TODO: Add a test for linux + desktop environment + ++ (lib.optionals pkgs.stdenv.isLinux [ + tree + cfspeedtest + ripgrep + helix + nil + ]) + # linux + desktop manager + #++ (lib.optionals (pkgs.stdenv.isLinux && osConfig.services.desktopManager.enabled != null) + #[ + # firefox + #]) + # darwin only + ++ (lib.optionals pkgs.stdenv.isDarwin [ + cfspeedtest + ripgrep + ]); + + programs.fish.enable = true; + # TODO: Get that working again. + #users.users.jml.shell = pkgs.fish; + + programs = { + bat.enable = true; + fzf.enable = true; + jq.enable = true; + btop.enable = true; + }; + + programs.git = { + enable = true; + userName = "Jay Looney"; + userEmail = "jay.m.looney@gmail.com"; + aliases = { + ol = "log --oneline"; + }; + ignores = [ "*~" "*.swp" ]; + extraConfig = { + push.default = "simple"; + credential.helper = "cache --timeout=7200"; + init.defaultBranch = "main"; + log.decorate = "full"; + log.date = "iso"; + merge.conflictStyle = "diff3"; + }; + }; +} diff --git a/users/jml/default.nix b/users/jml/default.nix index 69afa40..592e6ba 100644 --- a/users/jml/default.nix +++ b/users/jml/default.nix @@ -1,9 +1,6 @@ { pkgs, lib, ... }: { programs.fish.enable = true; - environment.systemPackages = [ - pkgs.home-manager - ]; users.users.jml = { shell = pkgs.fish; home = diff --git a/users/jml/home.nix b/users/jml/home.nix index e2fa5eb..e6170c6 100644 --- a/users/jml/home.nix +++ b/users/jml/home.nix @@ -1,10 +1,4 @@ -{ - username, - pkgs, - lib, - inputs, - ... -}: +{ username, pkgs, lib, ... }: { nixpkgs.config.allowUnfree = true; # The following line is needed if I start using hyprland Home Manager Module @@ -16,8 +10,8 @@ sessionVariables = { EDITOR = "hx"; }; - - homeDirectory = + + homeDirectory = if pkgs.stdenv.isLinux then lib.mkDefault "/home/${username}" else if pkgs.stdenv.isDarwin then @@ -25,26 +19,24 @@ else abort "Unsupported OS"; }; - home.packages = - with pkgs; - [ ] - # linux only - # TODO: Add a test for linux + desktop environment - ++ (lib.optionals pkgs.stdenv.isLinux [ - cfspeedtest - helix - nil - ]) - # linux + desktop manager - #++ (lib.optionals (pkgs.stdenv.isLinux && osConfig.services.desktopManager.enabled != null) - #[ - # firefox - #]) - # darwin only - ++ (lib.optionals pkgs.stdenv.isDarwin [ - cfspeedtest - ripgrep - ]); + home.packages = with pkgs; [ ] + # linux only + # TODO: Add a test for linux + desktop environment + ++ (lib.optionals pkgs.stdenv.isLinux [ + cfspeedtest + helix + nil + ]) + # linux + desktop manager + #++ (lib.optionals (pkgs.stdenv.isLinux && osConfig.services.desktopManager.enabled != null) + #[ + # firefox + #]) + # darwin only + ++ (lib.optionals pkgs.stdenv.isDarwin [ + cfspeedtest + ripgrep + ]); programs = { fish.enable = true; @@ -57,7 +49,7 @@ # Matrix Chat Apps element-desktop.enable = true; - #nheko.settings = true; + nheko.settings = true; # Additions from Windows obsidian.enable = true; @@ -73,11 +65,6 @@ helix.enable = true; zoxide.enable = true; fd.enable = true; - - difftastic.enable = true; - difftastic.git.enable = true; - difftastic.git.diffToolMode = true; - mergiraf.enable = true; }; programs.starship = { @@ -113,7 +100,7 @@ Cryptomining = true; Fingerprinting = true; }; - + Homepage.StartPage = "previous-session"; FirefoxHome = { Search = true; @@ -146,390 +133,34 @@ id = 0; name = "default"; isDefault = true; - settings = { + settings = { "widget.disable-workspace-management" = true; }; search = { force = true; - default = "ddg"; # DuckDuckGo + default = "ddg"; # DuckDuckGo }; }; }; }; - # TODO: figure out how to get config.programs..enable style - # internal references inside this file. - # There's some quirks with how this is used in lib/default.nix - # TODO: Use mergiraf for conflict resolution in jj too. - programs.jujutsu = { - enable = true; - #enableFishIntegration = true; - settings = { - user = { - name = "Jay Looney"; - email = "jay.m.looney@gmail.com"; - }; - }; - }; - - # TODO: Configure Mergiraf - # https://mergiraf.org/introduction.html programs.git = { enable = true; - settings = { - user = { - name = "Jay Looney"; - email = "jay.m.looney@gmail.com"; - }; - - # Aliases Inspired by the following: - # https://joel-hanson.github.io/posts/05-useful-git-aliases-for-a-productive-workflow/ - # https://gist.github.com/mwhite/6887990 - aliases = { - la = "!git config -l | grep alias | cut -c 7-"; - s = "status -s"; - co = "checkout"; - cob = "checkout -b"; - del = "branch -D"; - ol = "log --oneline"; - - br = "branch --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(contents:subject) %(color:green)(%(committerdate:relative)) [%(authorname)]' --sort=-committerdate"; - save = "!git add -A && git commit -m 'chore: commit save point'"; - undo = "reset HEAD~1 --mixed"; - done = "!git push origin HEAD"; - lg = "!git log --pretty=format:\"%C(magenta)%h%Creset -%C(red)%d%Creset %s %C(dim green)(%cr) [%an]\" --abbrev-commit -30"; - a = "add"; - ap = "add -p"; - }; - + userName = "Jay Looney"; + userEmail = "jay.m.looney@gmail.com"; + aliases = { + ol = "log --oneline"; + }; + ignores = [ "*~" "*.swp" ]; + extraConfig = { push.default = "simple"; credential.helper = "cache --timeout=7200"; init.defaultBranch = "main"; log.decorate = "full"; log.date = "iso"; - # NOTE: Initially diff3 was for me, now it's for me and mergiraf automation. merge.conflictStyle = "diff3"; }; - # Cribbed from: https://github.com/gitattributes/gitattributes - attributes = [ - # Auto detect files and perform LF normalization - "* text=auto" - # Documents - "*.bibtex text diff=bibtex" - "*.doc diff=astextplain" - "*.DOC diff=astextplain" - "*.docx diff=astextplain" - "*.DOCX diff=astextplain" - "*.dot diff=astextplain" - "*.DOT diff=astextplain" - "*.pdf diff=astextplain" - "*.PDF diff=astextplain" - "*.rtf diff=astextplain" - "*.RTF diff=astextplain" - "*.md text diff=markdown" - "*.mdx text diff=markdown" - "*.tex text diff=tex" - "*.adoc text" - "*.textile text" - "*.mustache text" - "*.csv text eol=crlf" - "*.tab text" - "*.tsv text" - "*.txt text" - "*.sql text" - "*.epub diff=astextplain" - - # Graphics - "*.png binary" - "*.jpg binary" - "*.jpeg binary" - "*.gif binary" - "*.tif binary" - "*.tiff binary" - "*.ico binary" - # SVG treated as text by default. - "*.svg text" - # If you want to treat it as binary, - # use the following line instead. - # *.svg binary - "*.eps binary" - - # Scripts - "*.bash text eol=lf" - "*.fish text eol=lf" - "*.ksh text eol=lf" - "*.sh text eol=lf" - "*.zsh text eol=lf" - # These are explicitly windows files and should use crlf - "*.bat text eol=crlf" - "*.cmd text eol=crlf" - "*.ps1 text eol=crlf" - - # Serialisation - "*.json text" - "*.toml text" - "*.xml text" - "*.yaml text" - "*.yml text" - - # Archives - "*.7z binary" - "*.bz binary" - "*.bz2 binary" - "*.bzip2 binary" - "*.gz binary" - "*.lz binary" - "*.lzma binary" - "*.rar binary" - "*.tar binary" - "*.taz binary" - "*.tbz binary" - "*.tbz2 binary" - "*.tgz binary" - "*.tlz binary" - "*.txz binary" - "*.xz binary" - "*.Z binary" - "*.zip binary" - "*.zst binary" - - # Text files where line endings should be preserved - "*.patch -text" - - # Exclude files from exporting - ".gitattributes export-ignore" - ".gitignore export-ignore" - ".gitkeep export-ignore" - ]; - # TODO: Merge Gitignores from here: https://github.com/github/gitignore/tree/main/Global - ignores = [ - "*~" - "*.swp" - ]; }; - programs.emacs = { - enable = true; - # package = (pkgs.emacs30.pkgs.withPackages (epkgs: [ - # epkgs.treesit-grammars.with-grammars (grammars: [ - # grammars.tree-sitter-bash - # ]) - # epkgs.pretty-sha-path - # ])); - extraConfig = '' - (setq standard-indent 2) - ''; - }; - - # TODO: Implement support for at least - # Nix, Python, Rust, Golang - # TODO: Sort out why TF, `.nix` files tabs are cooked in neovim rn. - # It corrects things on document save, but this line for example started with an 8-long tabstop - programs.nvf = { - enable = true; - # When using the Home-Manager Module for nvf, the settings go into the following attribute set. - # https://notashelf.github.io/nvf/index.xhtml#sec-hm-flakes - settings.vim = { - viAlias = true; - vimAlias = true; - - # TODO: For some reason spellcheck is having a very difficult time getting - # a wordlist. - #spellcheck = { - # enable = true; - # programmingWordlist.enable = true; - #}; - - lsp = { - enable = true; - formatOnSave = true; - lspkind.enable = false; - lightbulb.enable = true; - lspsaga.enable = false; - trouble.enable = true; - lspSignature.enable = false; - otter-nvim.enable = true; - nvim-docs-view.enable = true; - }; - - languages = { - enableDAP = true; - enableExtraDiagnostics = true; - enableFormat = true; - enableTreesitter = true; - - nix = { - enable = true; - lsp.enable = true; - lsp.server = "nixd"; - extraDiagnostics.enable = true; - format.enable = true; - format.type = "nixfmt"; - treesitter.enable = true; - }; - markdown.enable = true; - typst.enable = true; - - assembly.enable = true; - bash.enable = true; - clang.enable = true; - - python.enable = true; - rust = { - enable = true; - # TODO: null_ls is now deprecated. - # https://github.com/NotAShelf/nvf/issues/1175 - # https://github.com/NotAShelf/nvf/blob/main/.github/CONTRIBUTING.md - crates.enable = true; - }; - go.enable = true; - zig.enable = true; - - ts.enable = true; - html.enable = true; - css.enable = true; - sql.enable = true; - }; - - visuals = { - nvim-scrollbar.enable = true; # Configurable Visual Scrollbar (Can pair with Cursor, ALE, Diagnostics, Gitsigns, and hlslens) - nvim-web-devicons.enable = true; # Nerdfont Icons for use by other plugins - nvim-cursorline.enable = true; # Highlight Words & Lines on the cursor - cinnamon-nvim.enable = true; # Smooth Scrolling for any movement command. - fidget-nvim.enable = true; # UI for Notifications & LSP Progress Messages - - highlight-undo.enable = true; # Highlight changed text after any non-insert actions - indent-blankline.enable = true; # Indentation Guides - }; - - statusline = { - lualine = { - # Fancy Status Line - enable = true; - theme = "catppuccin"; - }; - }; - - theme = { - enable = true; - name = "catppuccin"; - style = "mocha"; - transparent = false; - }; - - autopairs.nvim-autopairs.enable = true; # Pair up ", {, (, etc. - # blink-cmp is a compiled rust binary while nvim-cmp is a pure lua plugin... - autocomplete.blink-cmp.enable = true; - # Code Snippets Engine /w support for Lua, VSCode, and SnipMate snippets. - snippets.luasnip.enable = true; - - filetree.neo-tree.enable = true; # Filesystem tree sidebar... - tabline.nvimBufferline.enable = true; # Shows buffers as tabs at the top. - treesitter.context.enable = true; - binds = { - whichKey.enable = true; # Shows your available keybindings in a popup - cheatsheet.enable = true; # Searchable in-editor cheatsheet that uses Telescope - }; - telescope.enable = true; # Fuzzy Finder, central to many other plugins. - - git = { - enable = true; - gitsigns.enable = true; # Git Info in Buffers + Gutters - gitsigns.codeActions.enable = false; - neogit.enable = true; # Interactive Git - }; - - # TODO: Consider switching to `minimap-nvim` for rust-based minimap. - # codewindow may be tightly integrated with treesitter though... - minimap.codewindow.enable = true; - dashboard.alpha.enable = true; # Greeter - notify.nvim-notify.enable = true; # Fancy Configurable Notification Manager - projects.project-nvim.enable = true; - - utility = { - ccc.enable = true; # Color Picker - diffview-nvim.enable = true; - icon-picker.enable = true; - surround.enable = true; # Change Surrounding Delimiter pairs `ysiw)` - leetcode-nvim.enable = true; # Allow solving LeetCode problems directly inside neovim - multicursors.enable = true; # Edit with multiple cursors simultaneously - smart-splits.enable = true; # Split-Pane Management - undotree.enable = true; # Undo history visualizer - nvim-biscuits.enable = true; # Shows the start of a code block from the bottom - - motion = { - # NOTE: https://github.com/smoka7/hop.nvim - hop.enable = true; # EasyMotion like, allowing you to jump anywhere in the document with as few keystrokes as possible - leap.enable = true; # Jump to anywhere visible - # TODO: I sort of hate how precognition injects itself in virtual - # lines, but I do like that it can be used to give a reminder. - precognition.enable = false; # Helps with discovering motions to navigate your current buffer - }; - images.img-clip.enable = true; - }; - - # TODO: Get Obsidian Working. - notes = { - # obsidian.enable = true; # neovim fails to build with this enabled. - mind-nvim.enable = true; - todo-comments.enable = true; - }; - - terminal = { - toggleterm = { - enable = true; - lazygit.enable = true; - }; - }; - - ui = { - borders.enable = true; - noice.enable = true; - colorizer.enable = true; - modes-nvim.enable = false; # this looks terrible with catppuccin - illuminate.enable = true; - breadcrumbs = { - enable = true; - navbuddy.enable = true; - }; - smartcolumn = { - enable = true; - setupOpts.custom_colorcolumn = { - nix = "110"; - ruby = "120"; - java = "130"; - go = [ - "90" - "130" - ]; - }; - }; - fastaction.enable = true; - }; - - assistant = { - chatgpt.enable = false; - copilot = { - enable = false; - cmp.enable = true; - }; - codecompanion-nvim.enable = false; - # avante-nvim.enable = true; - }; - - session.nvim-session-manager.enable = true; # Save sessions to reopen later - gestures.gesture-nvim.enable = false; # mouse gesture support? - comments.comment-nvim.enable = true; # Fancy commenting - presence.neocord.enable = true; # Discord Rich Presence - }; - }; - - programs.vscode = { - enable = true; - mutableExtensionsDir = true; # mutually exclusive to programs.vscode.profiles - # profiles.default.userSettings = { - # "[nix]"."editor.tabSize" = 2; - # }; - }; # services.podman.enable = true; }