diff --git a/.gitignore b/.gitignore index 21fb0b6..73105bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,13 @@ -result/ +# Nix build outputs +result +result-* .direnv/ -.pre-commit-config.yaml +oci-trantor/ +tailscale-tailnet/ +cloudflare-baduhaidev + +# Personal notes and temporary files +todo.md +notes.md +scratch/ +tmp/ diff --git a/deploy.nix b/deploy.nix new file mode 100644 index 0000000..187c92f --- /dev/null +++ b/deploy.nix @@ -0,0 +1,48 @@ +{ inputs, self, ... }: +{ + flake.deploy = { + remoteBuild = true; + nodes = { + alexandria = { + hostname = "alexandria"; + profiles.system = { + sshUser = "user"; + path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.alexandria; + user = "root"; + }; + }; + + trantor = { + hostname = "trantor"; + profiles.system = { + sshUser = "user"; + path = inputs.deploy-rs.lib.aarch64-linux.activate.nixos self.nixosConfigurations.trantor; + user = "root"; + }; + }; + + io = { + hostname = "io"; + profiles = { + system = { + sshUser = "user"; + path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.io; + user = "root"; + remoteBuild = false; + }; + user = { + sshUser = "user"; + path = inputs.deploy-rs.lib.x86_64-linux.activate.home-manager self.homeConfigurations."user@io"; + user = "user"; + remoteBuild = false; + }; + }; + }; + }; + }; + perSystem = + { system, ... }: + { + checks = inputs.deploy-rs.lib.${system}.deployChecks self.deploy; + }; +} diff --git a/devShells.nix b/devShells.nix new file mode 100644 index 0000000..f7e9627 --- /dev/null +++ b/devShells.nix @@ -0,0 +1,16 @@ +{ inputs, ... }: + +{ + perSystem = + { pkgs, system, ... }: + { + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + inputs.agenix.packages.${system}.default + deploy-rs + nil + nixfmt-rfc-style + ]; + }; + }; +} diff --git a/flake.lock b/flake.lock index 1541b54..27c3580 100644 --- a/flake.lock +++ b/flake.lock @@ -5,16 +5,16 @@ "darwin": "darwin", "home-manager": "home-manager", "nixpkgs": [ - "nixpkgs" + "nixpkgs-stable" ], "systems": "systems" }, "locked": { - "lastModified": 1736955230, - "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=", + "lastModified": 1761656077, + "narHash": "sha256-lsNWuj4Z+pE7s0bd2OKicOFq9bK86JE0ZGeKJbNqb94=", "owner": "ryantm", "repo": "agenix", - "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c", + "rev": "9ba0d85de3eaa7afeab493fed622008b6e4924f5", "type": "github" }, "original": { @@ -28,11 +28,11 @@ "fromYaml": "fromYaml" }, "locked": { - "lastModified": 1732200724, - "narHash": "sha256-+R1BH5wHhfnycySb7Sy5KbYEaTJZWm1h+LW1OtyhiTs=", + "lastModified": 1755819240, + "narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=", "owner": "SenchoPens", "repo": "base16.nix", - "rev": "153d52373b0fb2d343592871009a286ec8837aec", + "rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6", "type": "github" }, "original": { @@ -44,27 +44,28 @@ "base16-fish": { "flake": false, "locked": { - "lastModified": 1622559957, - "narHash": "sha256-PebymhVYbL8trDVVXxCvZgc0S5VxI7I1Hv4RMSquTpA=", + "lastModified": 1754405784, + "narHash": "sha256-l9xHIy+85FN+bEo6yquq2IjD1rSg9fjfjpyGP1W8YXo=", "owner": "tomyun", "repo": "base16-fish", - "rev": "2f6dd973a9075dabccd26f1cded09508180bf5fe", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", "type": "github" }, "original": { "owner": "tomyun", "repo": "base16-fish", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", "type": "github" } }, "base16-helix": { "flake": false, "locked": { - "lastModified": 1736852337, - "narHash": "sha256-esD42YdgLlEh7koBrSqcT7p2fsMctPAcGl/+2sYJa2o=", + "lastModified": 1752979451, + "narHash": "sha256-0CQM+FkYy0fOO/sMGhOoNL80ftsAzYCg9VhIrodqusM=", "owner": "tinted-theming", "repo": "base16-helix", - "rev": "03860521c40b0b9c04818f2218d9cc9efc21e7a5", + "rev": "27cf1e66e50abc622fb76a3019012dc07c678fac", "type": "github" }, "original": { @@ -90,6 +91,28 @@ "type": "github" } }, + "blueprint": { + "inputs": { + "nixpkgs": [ + "nix-ai-tools", + "nixpkgs" + ], + "systems": "systems_3" + }, + "locked": { + "lastModified": 1763308703, + "narHash": "sha256-O9Y+Wer8wOh+N+4kcCK5p/VLrXyX+ktk0/s3HdZvJzk=", + "owner": "numtide", + "repo": "blueprint", + "rev": "5a9bba070f801d63e2af3c9ef00b86b212429f4f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "blueprint", + "type": "github" + } + }, "darwin": { "inputs": { "nixpkgs": [ @@ -98,11 +121,11 @@ ] }, "locked": { - "lastModified": 1700795494, - "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "lastModified": 1744478979, + "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", "owner": "lnl7", "repo": "nix-darwin", - "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "rev": "43975d782b418ebf4969e9ccba82466728c2851b", "type": "github" }, "original": { @@ -115,17 +138,15 @@ "deploy-rs": { "inputs": { "flake-compat": "flake-compat", - "nixpkgs": [ - "nixpkgs" - ], + "nixpkgs": "nixpkgs", "utils": "utils" }, "locked": { - "lastModified": 1727447169, - "narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=", + "lastModified": 1756719547, + "narHash": "sha256-N9gBKUmjwRKPxAafXEk1EGadfk2qDZPBQp4vXWPHINQ=", "owner": "serokell", "repo": "deploy-rs", - "rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76", + "rev": "125ae9e3ecf62fb2c0fd4f2d894eb971f1ecaed2", "type": "github" }, "original": { @@ -134,14 +155,32 @@ "type": "github" } }, + "disko": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1761899396, + "narHash": "sha256-XOpKBp6HLzzMCbzW50TEuXN35zN5WGQREC7n34DcNMM=", + "owner": "nix-community", + "repo": "disko", + "rev": "6f4cf5abbe318e4cd1e879506f6eeafd83f7b998", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "firefox-gnome-theme": { "flake": false, "locked": { - "lastModified": 1736899990, - "narHash": "sha256-S79Hqn2EtSxU4kp99t8tRschSifWD4p/51++0xNWUxw=", + "lastModified": 1758112371, + "narHash": "sha256-lizRM2pj6PHrR25yimjyFn04OS4wcdbc38DCdBVa2rk=", "owner": "rafaelmardojai", "repo": "firefox-gnome-theme", - "rev": "91ca1f82d717b02ceb03a3f423cbe8082ebbb26d", + "rev": "0909cfe4a2af8d358ad13b20246a350e14c2473d", "type": "github" }, "original": { @@ -151,38 +190,6 @@ } }, "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_3": { "flake": false, "locked": { "lastModified": 1733328505, @@ -198,16 +205,92 @@ "type": "github" } }, - "flake-utils": { + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1761588595, + "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { "inputs": { - "systems": "systems_3" + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "lastModified": 1762040540, + "narHash": "sha256-z5PlZ47j50VNF3R+IMS9LmzI5fYRGY/Z5O5tol1c9I4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "0010412d62a25d959151790968765a70c436598b", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "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" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": [ + "terranix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1736143030, + "narHash": "sha256-+hu54pAoLDEZT9pjHlqL9DNzWz0NbUn8NEAHP7PQPzU=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "b905f6fc23a9051a6e1b741e1438dbfc0634c6de", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -218,10 +301,7 @@ }, "flake-utils_2": { "inputs": { - "systems": [ - "stylix", - "systems" - ] + "systems": "systems_8" }, "locked": { "lastModified": 1731533236, @@ -253,67 +333,19 @@ "type": "github" } }, - "git-hooks": { - "inputs": { - "flake-compat": [ - "stylix", - "flake-compat" - ], - "gitignore": "gitignore", - "nixpkgs": [ - "stylix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1735882644, - "narHash": "sha256-3FZAG+pGt3OElQjesCAWeMkQ7C/nB1oTHLRQ8ceP110=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "a5a961387e75ae44cc20f0a57ae463da5e959656", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "stylix", - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "gnome-shell": { "flake": false, "locked": { - "lastModified": 1732369855, - "narHash": "sha256-JhUWbcYPjHO3Xs3x9/Z9RuqXbcp5yhPluGjwsdE2GMg=", + "lastModified": 1748186689, + "narHash": "sha256-UaD7Y9f8iuLBMGHXeJlRu6U1Ggw5B9JnkFs3enZlap0=", "owner": "GNOME", "repo": "gnome-shell", - "rev": "dadd58f630eeea41d645ee225a63f719390829dc", + "rev": "8c88f917db0f1f0d80fa55206c863d3746fa18d0", "type": "github" }, "original": { "owner": "GNOME", - "ref": "47.2", + "ref": "48.2", "repo": "gnome-shell", "type": "github" } @@ -326,11 +358,11 @@ ] }, "locked": { - "lastModified": 1703113217, - "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", "owner": "nix-community", "repo": "home-manager", - "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", "type": "github" }, "original": { @@ -339,27 +371,6 @@ "type": "github" } }, - "home-manager-stable": { - "inputs": { - "nixpkgs": [ - "nixpkgs-stable" - ] - }, - "locked": { - "lastModified": 1736373539, - "narHash": "sha256-dinzAqCjenWDxuy+MqUQq0I4zUSfaCvN9rzuCmgMZJY=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "bd65bc3cde04c16755955630b344bc9e35272c56", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "release-24.11", - "repo": "home-manager", - "type": "github" - } - }, "home-manager_2": { "inputs": { "nixpkgs": [ @@ -367,11 +378,11 @@ ] }, "locked": { - "lastModified": 1738448366, - "narHash": "sha256-4ATtQqBlgsGqkHTemta0ydY6f7JBRXz4Hf574NHQpkg=", + "lastModified": 1762178366, + "narHash": "sha256-I+8yE5HVR2SFcHnW0771psQ/zn0qVzsKHY/gUM0nEVM=", "owner": "nix-community", "repo": "home-manager", - "rev": "18fa9f323d8adbb0b7b8b98a8488db308210ed93", + "rev": "8c824254b1ed9e797f6235fc3c62f365893c561a", "type": "github" }, "original": { @@ -384,16 +395,16 @@ "home-manager_3": { "inputs": { "nixpkgs": [ - "stylix", + "zen-browser", "nixpkgs" ] }, "locked": { - "lastModified": 1736785676, - "narHash": "sha256-TY0jUwR3EW0fnS0X5wXMAVy6h4Z7Y6a3m+Yq++C9AyE=", + "lastModified": 1752603129, + "narHash": "sha256-S+wmHhwNQ5Ru689L2Gu8n1OD6s9eU9n9mD827JNR+kw=", "owner": "nix-community", "repo": "home-manager", - "rev": "fc52a210b60f2f52c74eac41a8647c1573d2071d", + "rev": "e8c19a3cec2814c754f031ab3ae7316b64da085b", "type": "github" }, "original": { @@ -402,22 +413,6 @@ "type": "github" } }, - "homepage": { - "flake": false, - "locked": { - "lastModified": 1727121984, - "narHash": "sha256-sbpLXaFeyIBrGbuw58jwxDcMupFqlqmPGO5/QUgI9eg=", - "owner": "AlexW00", - "repo": "StartTreeV2", - "rev": "cfb8b97b14b23b094878867bef94e3c17a144f3f", - "type": "github" - }, - "original": { - "owner": "AlexW00", - "repo": "StartTreeV2", - "type": "github" - } - }, "impermanence": { "locked": { "lastModified": 1737831083, @@ -433,34 +428,130 @@ "type": "github" } }, + "niri": { + "inputs": { + "nixpkgs": "nixpkgs_3", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1760963745, + "narHash": "sha256-FVf9YFw2wQnMAxvMxEk+vFakXhPQUSapDpGmlLzAxjg=", + "owner": "baduhai", + "repo": "niri", + "rev": "dd3e3d1009991ecd87ab7253c9e7696acf2bc943", + "type": "github" + }, + "original": { + "owner": "baduhai", + "ref": "auto-center-when-space-available", + "repo": "niri", + "type": "github" + } + }, + "niri-flake": { + "inputs": { + "niri-stable": "niri-stable", + "niri-unstable": "niri-unstable", + "nixpkgs": "nixpkgs_4", + "nixpkgs-stable": "nixpkgs-stable", + "xwayland-satellite-stable": "xwayland-satellite-stable", + "xwayland-satellite-unstable": "xwayland-satellite-unstable" + }, + "locked": { + "lastModified": 1762152856, + "narHash": "sha256-U3SDbk7tIwLChpvb3FL66o8V0byaQ2RGMiy/3oLdxTI=", + "owner": "sodiboo", + "repo": "niri-flake", + "rev": "df17789929ac80f4157b15724450db6a303a6dc9", + "type": "github" + }, + "original": { + "owner": "sodiboo", + "repo": "niri-flake", + "type": "github" + } + }, + "niri-stable": { + "flake": false, + "locked": { + "lastModified": 1756556321, + "narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=", + "owner": "YaLTeR", + "repo": "niri", + "rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294", + "type": "github" + }, + "original": { + "owner": "YaLTeR", + "ref": "v25.08", + "repo": "niri", + "type": "github" + } + }, + "niri-unstable": { + "flake": false, + "locked": { + "lastModified": 1762146685, + "narHash": "sha256-anRlNG6t7esBbF1+ALDeathVBSclA0PEL52Vo0WnN5g=", + "owner": "YaLTeR", + "repo": "niri", + "rev": "a2ca2b3c866bc781b12c334a9f949b3db6d7c943", + "type": "github" + }, + "original": { + "owner": "YaLTeR", + "repo": "niri", + "type": "github" + } + }, + "nix-ai-tools": { + "inputs": { + "blueprint": "blueprint", + "nixpkgs": "nixpkgs_5", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1763412165, + "narHash": "sha256-n6bChFrCf2/uHzTsZdABUt1+Ua3n0jinNfamHd5DmBA=", + "owner": "numtide", + "repo": "nix-ai-tools", + "rev": "a2dfa932ed37e5b6224b39b4982c85cd8ebcca14", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-ai-tools", + "type": "github" + } + }, "nix-flatpak": { "locked": { - "lastModified": 1711997201, - "narHash": "sha256-J71xzQlVYsjagA4AsVwRazhBh2rZrPpKvxTgs6UzL7c=", + "lastModified": 1754777568, + "narHash": "sha256-0bBqT+3XncgF8F03RFAamw9vdf0VmaDoIJLTGkjfQZs=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "b76fa31346db7fc958a9898f3c594696ca71c4fd", + "rev": "62f636b87ef6050760a8cb325cadb90674d1e23e", "type": "github" }, "original": { "owner": "gmodena", - "ref": "v0.4.1", + "ref": "main", "repo": "nix-flatpak", "type": "github" } }, - "nix-index-db": { + "nix-index-database": { "inputs": { "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1738466368, - "narHash": "sha256-PZhUjtvQZOH3PO0EYdTpQvcqkgkq1NkP2A6w9SPHYsk=", + "lastModified": 1762055842, + "narHash": "sha256-Pu1v3mlFhRzZiSxVHb2/i/f5yeYyRNqr0RvEUJ4UgHo=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "46a8f5fc9552b776bfc5c5c96ea3bede33f68f52", + "rev": "359ff6333a7b0b60819d4c20ed05a3a1f726771f", "type": "github" }, "original": { @@ -469,103 +560,181 @@ "type": "github" } }, - "nix-minecraft": { + "nix-options-doc": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs_6", + "rust-overlay": "rust-overlay_2" + }, + "locked": { + "lastModified": 1742115705, + "narHash": "sha256-RfXwJPWBoWswIU68+y/XZfTWtFHd/fK14bKvOlRmfPo=", + "owner": "Thunderbottom", + "repo": "nix-options-doc", + "rev": "2caa4b5756a8666d65d70122f413e295f56886e7", + "type": "github" + }, + "original": { + "owner": "Thunderbottom", + "ref": "v0.2.0", + "repo": "nix-options-doc", + "type": "github" + } + }, + "nixos-cli": { "inputs": { "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ] + "nix-options-doc": "nix-options-doc", + "nixpkgs": "nixpkgs_7" }, "locked": { - "lastModified": 1738547119, - "narHash": "sha256-cc6AfR7W0AavgqA5nHUXRUus4Rr7oPWQNku5nhR4SYs=", - "owner": "Infinidoge", - "repo": "nix-minecraft", - "rev": "5b93268c80c3300dbec0fbbb2b50f674f84a474a", - "type": "github" - }, - "original": { - "owner": "Infinidoge", - "repo": "nix-minecraft", - "type": "github" - } - }, - "nixlib": { - "locked": { - "lastModified": 1736643958, - "narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=", + "lastModified": 1761970410, + "narHash": "sha256-IUm2nkbKlDkG94ruTmIYLERpBn6gXydm3scZIKzpcKs=", "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181", + "repo": "nixos-cli", + "rev": "5c259f72ae1eaa00b99354d81130d8fddb7f9a7a", "type": "github" }, "original": { "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" - } - }, - "nixos-generators": { - "inputs": { - "nixlib": "nixlib", - "nixpkgs": [ - "nixpkgs-stable" - ] - }, - "locked": { - "lastModified": 1737057290, - "narHash": "sha256-3Pe0yKlCc7EOeq1X/aJVDH0CtNL+tIBm49vpepwL1MQ=", - "owner": "nix-community", - "repo": "nixos-generators", - "rev": "d002ce9b6e7eb467cd1c6bb9aef9c35d191b5453", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixos-generators", + "repo": "nixos-cli", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1738410390, - "narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=", - "owner": "nixos", + "lastModified": 1743014863, + "narHash": "sha256-jAIUqsiN2r3hCuHji80U7NNEafpIMBXiwKlSrjWMlpg=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "3a228057f5b619feb3186e986dbe76278d707b6e", + "rev": "bd3bac8bfb542dbde7ffffb6987a1a1f9d41699f", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-unstable", + "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1761765539, + "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, "nixpkgs-stable": { "locked": { - "lastModified": 1738435198, - "narHash": "sha256-5+Hmo4nbqw8FrW85FlNm4IIrRnZ7bn0cmXlScNsNRLo=", + "lastModified": 1761999846, + "narHash": "sha256-IYlYnp4O4dzEpL77BD/lj5NnJy2J8qbHkNSFiPBCbqo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3de8f8d73e35724bf9abef41f1bdbedda1e14a31", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1761999846, + "narHash": "sha256-IYlYnp4O4dzEpL77BD/lj5NnJy2J8qbHkNSFiPBCbqo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "f6687779bf4c396250831aa5a32cbfeb85bb07a3", + "rev": "3de8f8d73e35724bf9abef41f1bdbedda1e14a31", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-24.11", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1762111121, + "narHash": "sha256-4vhDuZ7OZaZmKKrnDpxLZZpGIJvAeMtK6FKLJYUtAdw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b3d51a0365f6695e7dd5cdf3e180604530ed33b4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1736798957, - "narHash": "sha256-qwpCtZhSsSNQtK4xYGzMiyEDhkNzOCz/Vfu4oL2ETsQ=", + "lastModified": 1752596105, + "narHash": "sha256-lFNVsu/mHLq3q11MuGkMhUUoSXEdQjCHvpReaGP1S2k=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9abb87b552b7f55ac8916b6fc9e5cb486656a2f3", + "rev": "dab3a6e781554f965bde3def0aa2fda4eb8f1708", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "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_4": { + "locked": { + "lastModified": 1761907660, + "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15", "type": "github" }, "original": { @@ -575,21 +744,218 @@ "type": "github" } }, + "nixpkgs_5": { + "locked": { + "lastModified": 1763312402, + "narHash": "sha256-3YJkOBrFpmcusnh7i8GXXEyh7qZG/8F5z5+717550Hk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "85a6c4a07faa12aaccd81b36ba9bfc2bec974fa1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1740695751, + "narHash": "sha256-D+R+kFxy1KsheiIzkkx/6L63wEHBYX21OIwlFV8JvDs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "6313551cd05425cd5b3e63fe47dbc324eabb15e4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1761880412, + "narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a7fc11be66bdfb5cdde611ee5ce381c183da8386", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1761907660, + "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1758690382, + "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e643668fd71b949c53f8626614b21ff71a07379d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "noctalia": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "quickshell": "quickshell", + "systems": "systems_5" + }, + "locked": { + "lastModified": 1762156721, + "narHash": "sha256-gHfzrTDSnNC5yRJwkZfP55fPHUc8DuB4OQEIBSQSs18=", + "owner": "noctalia-dev", + "repo": "noctalia-shell", + "rev": "5ca5aa602f58a8e0e73fedbef351f1cdf8cbe981", + "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" + } + }, + "quickshell": { + "inputs": { + "nixpkgs": [ + "noctalia", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1761821581, + "narHash": "sha256-nLuc6jA7z+H/6bHPEBSOYPbz7RtvNCZiTKmYItJuBmM=", + "ref": "refs/heads/master", + "rev": "db1777c20b936a86528c1095cbcb1ebd92801402", + "revCount": 699, + "type": "git", + "url": "https://git.outfoxxed.me/outfoxxed/quickshell" + }, + "original": { + "type": "git", + "url": "https://git.outfoxxed.me/outfoxxed/quickshell" + } + }, "root": { "inputs": { "agenix": "agenix", "deploy-rs": "deploy-rs", + "disko": "disko", + "flake-parts": "flake-parts", "home-manager": "home-manager_2", - "home-manager-stable": "home-manager-stable", - "homepage": "homepage", "impermanence": "impermanence", + "niri": "niri", + "niri-flake": "niri-flake", + "nix-ai-tools": "nix-ai-tools", "nix-flatpak": "nix-flatpak", - "nix-index-db": "nix-index-db", - "nix-minecraft": "nix-minecraft", - "nixos-generators": "nixos-generators", - "nixpkgs": "nixpkgs", - "nixpkgs-stable": "nixpkgs-stable", - "stylix": "stylix" + "nix-index-database": "nix-index-database", + "nixos-cli": "nixos-cli", + "nixpkgs": "nixpkgs_8", + "nixpkgs-stable": "nixpkgs-stable_2", + "noctalia": "noctalia", + "stylix": "stylix", + "terranix": "terranix", + "vicinae": "vicinae", + "zen-browser": "zen-browser" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "niri", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1757989933, + "narHash": "sha256-9cpKYWWPCFhgwQTww8S94rTXgg8Q8ydFv9fXM6I8xQM=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "8249aa3442fb9b45e615a35f39eca2fe5510d7c3", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { + "inputs": { + "nixpkgs": [ + "nixos-cli", + "nix-options-doc", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1740796337, + "narHash": "sha256-FuoXrXZPoJEZQ3PF7t85tEpfBVID9JQIOnVKMNfTAb0=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "bbac9527bc6b28b6330b13043d0e76eac11720dc", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" } }, "stylix": { @@ -599,24 +965,23 @@ "base16-helix": "base16-helix", "base16-vim": "base16-vim", "firefox-gnome-theme": "firefox-gnome-theme", - "flake-compat": "flake-compat_3", - "flake-utils": "flake-utils_2", - "git-hooks": "git-hooks", + "flake-parts": "flake-parts_2", "gnome-shell": "gnome-shell", - "home-manager": "home-manager_3", - "nixpkgs": "nixpkgs_2", - "systems": "systems_4", + "nixpkgs": "nixpkgs_9", + "nur": "nur", + "systems": "systems_6", "tinted-foot": "tinted-foot", "tinted-kitty": "tinted-kitty", + "tinted-schemes": "tinted-schemes", "tinted-tmux": "tinted-tmux", "tinted-zed": "tinted-zed" }, "locked": { - "lastModified": 1738278499, - "narHash": "sha256-q1SUyXSQ9znHTME53/vPLe+Ga3V1wW3X3gWfa8JsBUM=", + "lastModified": 1762101397, + "narHash": "sha256-wGiL2K3kAyBBmIZpJEskaSIgyzzpg0zwfvri+Sy6/CI=", "owner": "danth", "repo": "stylix", - "rev": "b00c9f46ae6c27074d24d2db390f0ac5ebcc329f", + "rev": "8c0640d5722a02178c8ee80a62c5f019cab4b3c1", "type": "github" }, "original": { @@ -685,6 +1050,88 @@ "type": "github" } }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_7": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_8": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "terranix": { + "inputs": { + "flake-parts": "flake-parts_3", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_7" + }, + "locked": { + "lastModified": 1762161791, + "narHash": "sha256-J1L1yP29NVBJO04LA/JGM6kwhnjeNhEsX0tLFnuN3FI=", + "owner": "terranix", + "repo": "terranix", + "rev": "a79a47b4617dfb92184e2e5b8f5aa6fc06c659c8", + "type": "github" + }, + "original": { + "owner": "terranix", + "repo": "terranix", + "type": "github" + } + }, "tinted-foot": { "flake": false, "locked": { @@ -705,28 +1152,43 @@ "tinted-kitty": { "flake": false, "locked": { - "lastModified": 1716423189, - "narHash": "sha256-2xF3sH7UIwegn+2gKzMpFi3pk5DlIlM18+vj17Uf82U=", + "lastModified": 1735730497, + "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=", "owner": "tinted-theming", "repo": "tinted-kitty", - "rev": "eb39e141db14baef052893285df9f266df041ff8", + "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa", "type": "github" }, "original": { "owner": "tinted-theming", "repo": "tinted-kitty", - "rev": "eb39e141db14baef052893285df9f266df041ff8", + "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": 1735737224, - "narHash": "sha256-FO2hRBkZsjlIRqzNHCPc/52yxg11kHGA8MEtSun9RwE=", + "lastModified": 1757811970, + "narHash": "sha256-n5ZJgmzGZXOD9pZdAl1OnBu3PIqD+X3vEBUGbTi4JiI=", "owner": "tinted-theming", "repo": "tinted-tmux", - "rev": "aead506a9930c717ebf81cc83a2126e9ca08fa64", + "rev": "d217ba31c846006e9e0ae70775b0ee0f00aa6b1e", "type": "github" }, "original": { @@ -738,11 +1200,11 @@ "tinted-zed": { "flake": false, "locked": { - "lastModified": 1725758778, - "narHash": "sha256-8P1b6mJWyYcu36WRlSVbuj575QWIFZALZMTg5ID/sM4=", + "lastModified": 1757811247, + "narHash": "sha256-4EFOUyLj85NRL3OacHoLGEo0wjiRJzfsXtR4CZWAn6w=", "owner": "tinted-theming", "repo": "base16-zed", - "rev": "122c9e5c0e6f27211361a04fae92df97940eccf9", + "rev": "824fe0aacf82b3c26690d14e8d2cedd56e18404e", "type": "github" }, "original": { @@ -751,16 +1213,37 @@ "type": "github" } }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nix-ai-tools", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762938485, + "narHash": "sha256-AlEObg0syDl+Spi4LsZIBrjw+snSVU4T8MOeuZJUJjM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "5b4ee75aeefd1e2d5a1cc43cf6ba65eba75e83e4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, "utils": { "inputs": { "systems": "systems_2" }, "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -768,6 +1251,77 @@ "repo": "flake-utils", "type": "github" } + }, + "vicinae": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_10" + }, + "locked": { + "lastModified": 1762709887, + "narHash": "sha256-8BoGGsWfkS/2ODBSCYd5HJNFGuLY8fFl27rXmWClXQw=", + "owner": "vicinaehq", + "repo": "vicinae", + "rev": "54722e36137d8273ef0a5db37776fb8302c79238", + "type": "github" + }, + "original": { + "owner": "vicinaehq", + "repo": "vicinae", + "type": "github" + } + }, + "xwayland-satellite-stable": { + "flake": false, + "locked": { + "lastModified": 1755491097, + "narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=", + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "rev": "388d291e82ffbc73be18169d39470f340707edaa", + "type": "github" + }, + "original": { + "owner": "Supreeeme", + "ref": "v0.7", + "repo": "xwayland-satellite", + "type": "github" + } + }, + "xwayland-satellite-unstable": { + "flake": false, + "locked": { + "lastModified": 1761622056, + "narHash": "sha256-fBrUszJXmB4MY+wf3QsCnqWHcz7u7fLq0QMAWCltIQg=", + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "rev": "0728d59ff6463a502e001fb090f6eb92dbc04756", + "type": "github" + }, + "original": { + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "type": "github" + } + }, + "zen-browser": { + "inputs": { + "home-manager": "home-manager_3", + "nixpkgs": "nixpkgs_11" + }, + "locked": { + "lastModified": 1762131860, + "narHash": "sha256-sIPhzkDrfe6ptthZiwoxQyO6rKd9PgJnl+LOyythQkI=", + "owner": "0xc000022070", + "repo": "zen-browser-flake", + "rev": "10e69cb268b1d3dc91135e72f5462b2acfbcc3aa", + "type": "github" + }, + "original": { + "owner": "0xc000022070", + "repo": "zen-browser-flake", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 81e961a..c5c3880 100644 --- a/flake.nix +++ b/flake.nix @@ -2,186 +2,76 @@ description = "My nix hosts"; inputs = { + flake-parts.url = "github:hercules-ci/flake-parts"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11"; + nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.05"; home-manager = { url = "github:nix-community/home-manager/master"; inputs.nixpkgs.follows = "nixpkgs"; }; - home-manager-stable = { - url = "github:nix-community/home-manager/release-24.11"; - inputs.nixpkgs.follows = "nixpkgs-stable"; - }; agenix = { url = "github:ryantm/agenix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - deploy-rs = { - url = "github:serokell/deploy-rs"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - homepage = { - url = "github:AlexW00/StartTreeV2"; - flake = false; - }; - - impermanence.url = "github:nix-community/impermanence"; - - nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=v0.4.1"; - - nix-index-db = { - url = "github:nix-community/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - nix-minecraft = { - url = "github:Infinidoge/nix-minecraft"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - nixos-generators = { - url = "github:nix-community/nixos-generators"; inputs.nixpkgs.follows = "nixpkgs-stable"; }; + disko.url = "github:nix-community/disko"; + + noctalia = { + url = "github:noctalia-dev/noctalia-shell"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + stylix.url = "github:danth/stylix"; + nixos-cli.url = "github:nix-community/nixos-cli"; + + nix-flatpak.url = "github:gmodena/nix-flatpak/main"; + + zen-browser.url = "github:0xc000022070/zen-browser-flake"; + + impermanence.url = "github:nix-community/impermanence"; + + deploy-rs.url = "github:serokell/deploy-rs"; + + niri-flake.url = "github:sodiboo/niri-flake"; + + niri.url = "github:baduhai/niri/auto-center-when-space-available"; + + nix-index-database = { + url = "github:nix-community/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + terranix = { + url = "github:terranix/terranix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + nix-ai-tools.url = "github:numtide/nix-ai-tools"; + + vicinae.url = "github:vicinaehq/vicinae"; }; outputs = - inputs@{ - self, - nixpkgs, - nixpkgs-stable, - home-manager, - home-manager-stable, - agenix, - deploy-rs, - homepage, - impermanence, - nix-flatpak, - nix-index-db, - nix-minecraft, - nixos-generators, - stylix, - ... - }: - { - nixosConfigurations = { - rotterdam = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - inherit inputs; - }; - modules = [ - ./hosts/desktops/rotterdam.nix - agenix.nixosModules.default - home-manager.nixosModules.default - impermanence.nixosModules.impermanence - nix-index-db.nixosModules.nix-index - nix-flatpak.nixosModules.nix-flatpak - stylix.nixosModules.stylix - { - nixpkgs.overlays = [ - agenix.overlays.default - self.overlays.custom - ]; - } - ]; - }; + inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; - io = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - inherit inputs; - }; - modules = [ - ./hosts/desktops/io.nix - agenix.nixosModules.default - home-manager.nixosModules.default - impermanence.nixosModules.impermanence - nix-index-db.nixosModules.nix-index - nix-flatpak.nixosModules.nix-flatpak - stylix.nixosModules.stylix - { - nixpkgs.overlays = [ - agenix.overlays.default - self.overlays.custom - ]; - } - ]; - }; - - alexandria = nixpkgs-stable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - inherit inputs; - }; - modules = [ - ./hosts/servers/alexandria.nix - agenix.nixosModules.default - home-manager-stable.nixosModules.default - self.nixosModules.qbittorrent - ({ - nixpkgs.overlays = [ - agenix.overlays.default - nix-minecraft.overlay - ]; - imports = [ nix-minecraft.nixosModules.minecraft-servers ]; - }) - ]; - }; - }; - - overlays = { - custom = final: prev: { - plasticity = nixpkgs.legacyPackages."x86_64-linux".callPackage ./packages/plasticity.nix { }; - }; - }; - - deploy = { - autoRollback = true; - magicRollback = false; - nodes = { - alexandria = { - hostname = "alexandria"; - profiles = { - system = { - user = "root"; - sshUser = "root"; - remoteBuild = true; - path = deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.alexandria; - }; - }; - }; - - io = { - hostname = "io"; - profiles = { - system = { - user = "root"; - sshUser = "root"; - remoteBuild = false; - path = deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.io; - }; - }; - }; - }; - }; - - formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt-rfc-style; - - devShells."x86_64-linux".default = nixpkgs.legacyPackages."x86_64-linux".mkShell { - packages = with nixpkgs.legacyPackages."x86_64-linux"; [ - nil - nixfmt-rfc-style - ]; - }; - - nixosModules.qbittorrent = import ./modules/qbittorrent.nix; + imports = [ + ./deploy.nix + ./devShells.nix + ./homeConfigurations.nix + ./nixosConfigurations.nix + ./nixosModules.nix + ./overlays.nix + ./packages.nix + ./terranixConfigurations.nix + ]; }; } diff --git a/homeConfigurations.nix b/homeConfigurations.nix new file mode 100644 index 0000000..296abfa --- /dev/null +++ b/homeConfigurations.nix @@ -0,0 +1,43 @@ +{ inputs, ... }: + +let + lib = inputs.nixpkgs.lib; + utils = import ./utils.nix { inherit inputs lib; }; + inherit (utils) mkHome; +in + +{ + flake.homeConfigurations = { + "user@rotterdam" = mkHome { + username = "user"; + hostname = "rotterdam"; + tags = [ + "desktop" + "btop" + "comma" + "direnv" + "gaming" + "helix" + "obs-studio" + "starship" + "stylix" + "tmux" + ]; + }; + + "user@io" = mkHome { + username = "user"; + hostname = "io"; + tags = [ + "desktop" + "btop" + "comma" + "direnv" + "helix" + "starship" + "stylix" + "tmux" + ]; + }; + }; +} diff --git a/hosts/servers/alexandria/hardware-configuration.nix b/hosts/alexandria/hardware-configuration.nix similarity index 66% rename from hosts/servers/alexandria/hardware-configuration.nix rename to hosts/alexandria/hardware-configuration.nix index a5f9767..63ecba5 100644 --- a/hosts/servers/alexandria/hardware-configuration.nix +++ b/hosts/alexandria/hardware-configuration.nix @@ -23,17 +23,23 @@ extraModulePackages = [ ]; }; - fileSystems."/" = { - device = "/dev/disk/by-uuid/31289617-1d84-4432-a833-680b52e88525"; - fsType = "ext4"; + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/31289617-1d84-4432-a833-680b52e88525"; + fsType = "ext4"; + }; + "/boot" = { + device = "/dev/disk/by-uuid/4130-BE54"; + fsType = "vfat"; + }; }; - fileSystems."/boot" = { - device = "/dev/disk/by-uuid/4130-BE54"; - fsType = "vfat"; - }; - - swapDevices = [ ]; + swapDevices = [ + { + device = "/swapfile"; + size = 8192; + } + ]; networking.useDHCP = lib.mkDefault true; diff --git a/hosts/alexandria/jellyfin.nix b/hosts/alexandria/jellyfin.nix new file mode 100644 index 0000000..6ceac09 --- /dev/null +++ b/hosts/alexandria/jellyfin.nix @@ -0,0 +1,15 @@ +{ lib, inputs, ... }: +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts; +in +{ + services.jellyfin = { + enable = true; + openFirewall = true; + }; + + services.nginx.virtualHosts = mkNginxVHosts { + domains."jellyfin.baduhai.dev".locations."/".proxyPass = "http://127.0.0.1:8096/"; + }; +} diff --git a/hosts/alexandria/kanidm.nix b/hosts/alexandria/kanidm.nix new file mode 100644 index 0000000..eaaa9b9 --- /dev/null +++ b/hosts/alexandria/kanidm.nix @@ -0,0 +1,83 @@ +{ + config, + lib, + inputs, + pkgs, + ... +}: + +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts; + kanidmCertDir = "/var/lib/kanidm/certs"; +in + +{ + services.kanidm = { + enableServer = true; + enableClient = true; + package = pkgs.kanidm; + + serverSettings = { + domain = "auth.baduhai.dev"; + origin = "https://auth.baduhai.dev"; + bindaddress = "127.0.0.1:8443"; + ldapbindaddress = "127.0.0.1:636"; + trust_x_forward_for = true; + # Use self-signed certificates for internal TLS + tls_chain = "${kanidmCertDir}/cert.pem"; + tls_key = "${kanidmCertDir}/key.pem"; + }; + + clientSettings = { + uri = "https://auth.baduhai.dev"; + }; + }; + + services.nginx.virtualHosts = mkNginxVHosts { + domains."auth.baduhai.dev" = { + locations."/" = { + proxyPass = "https://127.0.0.1:8443"; + extraConfig = '' + proxy_ssl_verify off; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; + ''; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 636 ]; + + # Generate self-signed certificates for kanidm's internal TLS + systemd.services.kanidm-generate-certs = { + description = "Generate self-signed TLS certificates for Kanidm"; + wantedBy = [ "multi-user.target" ]; + before = [ "kanidm.service" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + mkdir -p ${kanidmCertDir} + if [ ! -f ${kanidmCertDir}/key.pem ]; then + ${pkgs.openssl}/bin/openssl req -x509 -newkey rsa:4096 \ + -keyout ${kanidmCertDir}/key.pem \ + -out ${kanidmCertDir}/cert.pem \ + -days 3650 -nodes \ + -subj "/CN=localhost" \ + -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" + chown -R kanidm:kanidm ${kanidmCertDir} + chmod 600 ${kanidmCertDir}/key.pem + chmod 644 ${kanidmCertDir}/cert.pem + fi + ''; + }; + + # Ensure certificate generation runs before kanidm starts + systemd.services.kanidm = { + after = [ "kanidm-generate-certs.service" ]; + wants = [ "kanidm-generate-certs.service" ]; + }; +} diff --git a/hosts/servers/alexandria/nextcloud.nix b/hosts/alexandria/nextcloud.nix similarity index 67% rename from hosts/servers/alexandria/nextcloud.nix rename to hosts/alexandria/nextcloud.nix index 04d7407..c449cce 100644 --- a/hosts/servers/alexandria/nextcloud.nix +++ b/hosts/alexandria/nextcloud.nix @@ -2,22 +2,37 @@ lib, config, pkgs, + inputs, ... }: +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts; +in + { services = { nextcloud = { enable = true; - package = pkgs.nextcloud30; + package = pkgs.nextcloud32; datadir = "/data/nextcloud"; hostName = "cloud.baduhai.dev"; configureRedis = true; https = true; - autoUpdateApps.enable = true; secretFile = config.age.secrets."nextcloud-secrets.json".path; database.createLocally = true; maxUploadSize = "16G"; + extraApps = { + inherit (config.services.nextcloud.package.packages.apps) + calendar + contacts + notes + tasks + user_oidc + ; + }; + extraAppsEnable = true; caching = { apcu = true; redis = true; @@ -26,6 +41,7 @@ trusted_proxies = [ "127.0.0.1" ]; default_phone_region = "BR"; maintenance_window_start = "4"; + allow_local_remote_servers = true; enabledPreviewProviders = [ "OC\\Preview\\BMP" "OC\\Preview\\EMF" @@ -61,43 +77,21 @@ }; }; - collabora-online = { - enable = true; - port = lib.strings.toInt config.ports.collabora; - settings.ssl = { - enable = false; - termination = true; - }; - }; - - nginx.virtualHosts = { - ${config.services.nextcloud.hostName} = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - }; - "office.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/" = { - proxyPass = "http://127.0.0.1:${config.ports.collabora}"; - proxyWebsockets = true; - }; - }; + nginx.virtualHosts = mkNginxVHosts { + domains."cloud.baduhai.dev" = { }; }; }; age.secrets = { "nextcloud-secrets.json" = { - file = ../../../secrets/nextcloud-secrets.json.age; + file = ../../secrets/nextcloud-secrets.json.age; owner = "nextcloud"; - group = "hosted"; + group = "nextcloud"; }; nextcloud-adminpass = { - file = ../../../secrets/nextcloud-adminpass.age; + file = ../../secrets/nextcloud-adminpass.age; owner = "nextcloud"; - group = "hosted"; + group = "nextcloud"; }; }; } diff --git a/hosts/alexandria/nginx.nix b/hosts/alexandria/nginx.nix new file mode 100644 index 0000000..274f645 --- /dev/null +++ b/hosts/alexandria/nginx.nix @@ -0,0 +1,59 @@ +{ + config, + lib, + inputs, + ... +}: + +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts services; + + # Get all unique domains from shared services that have LAN IPs (served by this host) + localDomains = lib.unique (map (s: s.domain) (lib.filter (s: s.host == "alexandria") services)); + + # Generate ACME cert configs for all local domains + acmeCerts = lib.genAttrs localDomains (domain: { + group = "nginx"; + }); +in + +{ + security.acme = { + acceptTerms = true; + defaults = { + email = "baduhai@proton.me"; + dnsResolver = "1.1.1.1:53"; + dnsProvider = "cloudflare"; + credentialsFile = config.age.secrets.cloudflare.path; + }; + certs = acmeCerts; + }; + + services.nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + virtualHosts = { + "_" = { + default = true; + locations."/".return = "444"; + }; + }; + }; + + users.users.nginx.extraGroups = [ "acme" ]; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + age.secrets.cloudflare = { + file = ../../secrets/cloudflare.age; + owner = "nginx"; + group = "nginx"; + }; +} diff --git a/hosts/alexandria/unbound.nix b/hosts/alexandria/unbound.nix new file mode 100644 index 0000000..31363aa --- /dev/null +++ b/hosts/alexandria/unbound.nix @@ -0,0 +1,58 @@ +{ inputs, lib, ... }: + +let + utils = import ../../utils.nix { inherit inputs lib; }; +in + +{ + services.unbound = { + enable = true; + enableRootTrustAnchor = true; + settings = { + server = { + interface = [ + "0.0.0.0" + "::" + ]; + access-control = [ + "127.0.0.0/8 allow" + "192.168.0.0/16 allow" + "::1/128 allow" + ]; + + num-threads = 2; + msg-cache-size = "50m"; + rrset-cache-size = "100m"; + cache-min-ttl = 300; + cache-max-ttl = 86400; + prefetch = true; + prefetch-key = true; + hide-identity = true; + hide-version = true; + so-rcvbuf = "1m"; + so-sndbuf = "1m"; + + # LAN-only DNS records + local-zone = ''"baduhai.dev." transparent''; + local-data = map (e: ''"${e.domain}. IN A ${e.lanIP}"'') + (lib.filter (e: e ? lanIP) utils.services); + }; + + forward-zone = [ + { + name = "."; + forward-addr = [ + "1.1.1.1@853#cloudflare-dns.com" + "1.0.0.1@853#cloudflare-dns.com" + ]; + forward-tls-upstream = true; + } + ]; + }; + }; + + networking.firewall = { + allowedTCPPorts = [ 53 ]; + allowedUDPPorts = [ 53 ]; + }; +} diff --git a/hosts/alexandria/vaultwarden.nix b/hosts/alexandria/vaultwarden.nix new file mode 100644 index 0000000..2335ee0 --- /dev/null +++ b/hosts/alexandria/vaultwarden.nix @@ -0,0 +1,26 @@ +{ + config, + lib, + inputs, + ... +}: +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts; +in +{ + services.vaultwarden = { + enable = true; + config = { + DOMAIN = "https://pass.baduhai.dev"; + SIGNUPS_ALLOWED = false; + ROCKET_ADDRESS = "127.0.0.1"; + ROCKET_PORT = 58222; + }; + }; + + services.nginx.virtualHosts = mkNginxVHosts { + domains."pass.baduhai.dev".locations."/".proxyPass = + "http://${config.services.vaultwarden.config.ROCKET_ADDRESS}:${toString config.services.vaultwarden.config.ROCKET_PORT}/"; + }; +} diff --git a/hosts/common/default.nix b/hosts/common/default.nix deleted file mode 100644 index aeb88ef..0000000 --- a/hosts/common/default.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./console.nix - ./locale.nix - ./networking.nix - ./nix.nix - ./packages.nix - ./security.nix - ./services.nix - ./users.nix - ./virtualisation.nix - ./environment.nix - ]; -} diff --git a/hosts/common/environment.nix b/hosts/common/environment.nix deleted file mode 100644 index 43d1dee..0000000 --- a/hosts/common/environment.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ pkgs, ... }: - -{ - environment.shellAliases = { - ls = "${pkgs.eza}/bin/eza --icons --group-directories-first"; - neofetch = "fastfetch"; - tree = "ls --tree"; - syscleanup = "sudo nix-collect-garbage -d; sudo /run/current-system/bin/switch-to-configuration boot"; - }; -} diff --git a/hosts/common/packages.nix b/hosts/common/packages.nix deleted file mode 100644 index 16463b3..0000000 --- a/hosts/common/packages.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ pkgs, ... }: - -{ - environment.systemPackages = with pkgs; [ - agenix - bind - btop - fastfetch - git - helix - killall - sysz - tmux - wget - ]; - - programs = { - fish.enable = true; - command-not-found.enable = false; - }; -} diff --git a/hosts/desktops/common/default.nix b/hosts/desktops/common/default.nix deleted file mode 100644 index bc5dc51..0000000 --- a/hosts/desktops/common/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./hardware.nix - ./home-manager.nix - ./impermanence.nix - ./nix.nix - ./packages.nix - ./services.nix - ./stylix.nix - ./users.nix - ./virtualisation.nix - ]; -} diff --git a/hosts/desktops/common/hardware.nix b/hosts/desktops/common/hardware.nix deleted file mode 100644 index 18cf38f..0000000 --- a/hosts/desktops/common/hardware.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ ... }: - -{ - hardware = { - xpadneo.enable = true; - bluetooth.enable = true; - steam-hardware.enable = true; # Allow steam client to manage controllers - graphics.enable32Bit = true; # For OpenGL games - i2c.enable = true; - }; - - security.rtkit.enable = true; # Needed for pipewire to acquire realtime priority -} diff --git a/hosts/desktops/common/home-manager.nix b/hosts/desktops/common/home-manager.nix deleted file mode 100644 index 6e88ad7..0000000 --- a/hosts/desktops/common/home-manager.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ ... }: - -{ - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - backupFileExtension = "bkp"; - users.user = import ../../../users/desktops/user.nix; - }; -} diff --git a/hosts/desktops/common/packages.nix b/hosts/desktops/common/packages.nix deleted file mode 100644 index 842e9a1..0000000 --- a/hosts/desktops/common/packages.nix +++ /dev/null @@ -1,137 +0,0 @@ -{ inputs, pkgs, ... }: -let - kdepkgs = with pkgs.kdePackages; [ - ark - dolphin-plugins - kolourpaint - ]; - kwrite = pkgs.symlinkJoin { - name = "kwrite"; - paths = [ pkgs.kdePackages.kate ]; - postBuild = '' - rm -rf $out/bin/kate \ - $out/bin/.kate-wrapped \ - $out/share/applications/org.kde.kate.desktop \ - $out/share/man \ - $out/share/icons/hicolor/*/apps/kate.png \ - $out/share/icons/hicolor/scalable/apps/kate.svg \ - $out/share/appdata/org.kde.kate.appdata.xml - ''; - }; -in -{ - environment.systemPackages = - with pkgs; - [ - adwaita-icon-theme - aspell - aspellDicts.de - aspellDicts.en - aspellDicts.en-computers - aspellDicts.pt_BR - bat - bitwarden-desktop - clonehero - deploy-rs - distrobox - fd - firefox - freecad-wayland - fzf - gimp - heroic - inkscape - junction - kara - kde-rounded-corners - kwrite - libfido2 - libreoffice-qt - # lilipod BROKEN - mangohud - microsoft-edge - mission-center - mpv - nextcloud-client - nixfmt-rfc-style - nixos-firewall-tool - nix-init - nix-output-monitor - obsidian - obs-studio - orca-slicer - p7zip - plasma-panel-colorizer - plasticity - protonup - quickemu - quickgui - qview - qbittorrent - ripgrep - rnote - steam-run - tor-browser - ungoogled-chromium - unrar - ventoy - vesktop - ] - ++ kdepkgs; - - services.flatpak = { - enable = true; - packages = [ - "com.github.k4zmu2a.spacecadetpinball" - "com.github.tchx84.Flatseal" - "com.modrinth.ModrinthApp" - "com.steamgriddb.SGDBoop" - "app.zen_browser.zen" - "io.github.Foldex.AdwSteamGtk" - "io.itch.itch" - "org.freedesktop.Platform.VulkanLayer.MangoHud/x86_64/24.08" - ]; - uninstallUnmanaged = true; - update.auto.enable = true; - }; - - programs = { - adb.enable = true; - steam.enable = true; - dconf.enable = true; - nix-ld.enable = true; - kdeconnect.enable = true; - partition-manager.enable = true; - gamemode.enable = true; - nix-index-database.comma.enable = true; - appimage = { - enable = true; - binfmt = true; - }; - nh = { - enable = true; - flake = "/home/user/Projects/personal/nix-config"; - }; - }; - - fonts = { - fontDir.enable = true; - packages = with pkgs; [ - corefonts - noto-fonts-cjk-sans - roboto - ]; - }; - - environment.plasma6.excludePackages = ( - with pkgs.kdePackages; - [ - discover - elisa - gwenview - kate - khelpcenter - oxygen - ] - ); -} diff --git a/hosts/desktops/common/services.nix b/hosts/desktops/common/services.nix deleted file mode 100644 index 12a64e9..0000000 --- a/hosts/desktops/common/services.nix +++ /dev/null @@ -1,61 +0,0 @@ -{ - inputs, - config, - pkgs, - ... -}: - -{ - services = { - printing.enable = true; - udev.packages = with pkgs; [ yubikey-personalization ]; - desktopManager.plasma6.enable = true; - tailscale.useRoutingFeatures = "client"; - nginx = { - enable = true; - virtualHosts."localhost".root = inputs.homepage; - }; - pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - jack.enable = true; - wireplumber.enable = true; - }; - greetd = { - enable = true; - settings = { - default_session.command = - let - xSessions = "${config.services.displayManager.sessionData.desktops}/share/xsessions"; - wlSessions = "${config.services.displayManager.sessionData.desktops}/share/wayland-sessions"; - in - '' - ${pkgs.greetd.tuigreet}/bin/tuigreet \ - --remember \ - --asterisks \ - --time \ - --greeting "NixOS" \ - --sessions ${xSessions}:${wlSessions} - ''; - initial_session = { - command = '' - ${pkgs.kdePackages.plasma-workspace}/bin/startplasma-wayland &> /dev/null - ''; - user = "user"; - }; - }; - }; - }; - - xdg.portal = { - enable = true; - xdgOpenUsePortal = true; - extraPortals = with pkgs; [ - xdg-desktop-portal-kde - xdg-desktop-portal-gtk - xdg-desktop-portal-gnome - ]; - }; -} diff --git a/hosts/desktops/common/users.nix b/hosts/desktops/common/users.nix deleted file mode 100644 index c62d425..0000000 --- a/hosts/desktops/common/users.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ ... }: - -{ - environment.sessionVariables = rec { - KDEHOME = "$XDG_CONFIG_HOME/kde4"; # Stops kde from placing a .kde4 folder in the home dir - NIXOS_OZONE_WL = "1"; # Forces chromium and most electron apps to run in wayland - }; - - users.users.user = { - description = "William"; - extraGroups = [ - "uaccess" # Needed for HID dev - "dialout" # Needed for arduino dev - "libvirt" - "libvirtd" - "adbusers" - "i2c" - ]; - }; -} diff --git a/hosts/desktops/common/virtualisation.nix b/hosts/desktops/common/virtualisation.nix deleted file mode 100644 index 461eb36..0000000 --- a/hosts/desktops/common/virtualisation.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: - -{ - virtualisation = { - libvirtd.enable = true; - lxd.enable = true; - }; -} diff --git a/hosts/desktops/io/default.nix b/hosts/desktops/io/default.nix deleted file mode 100644 index a480ae0..0000000 --- a/hosts/desktops/io/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: - -{ - imports = [ - ./ephermal.nix - ./hardware-configuration.nix - ]; -} diff --git a/hosts/desktops/io/ephermal.nix b/hosts/desktops/io/ephermal.nix deleted file mode 100644 index 35542f8..0000000 --- a/hosts/desktops/io/ephermal.nix +++ /dev/null @@ -1,46 +0,0 @@ -{ ... }: - -{ - boot.initrd.systemd.services.recreate-root = { - description = "Rolling over and creating new filesystem root"; - requires = [ "initrd-root-device.target" ]; - after = [ - "local-fs-pre.target" - "initrd-root-device.target" - ]; - requiredBy = [ "initrd-root-fs.target" ]; - before = [ "sysroot.mount" ]; - unitConfig = { - AssertPathExists = "/etc/initrd-release"; - DefaultDependencies = false; - }; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - script = '' - mkdir /btrfs_tmp - mount /dev/disk/by-uuid/3638cea6-5503-43cc-aa4f-3d37ebedad2f /btrfs_tmp - if [[ -e /btrfs_tmp/@root ]]; then - mkdir -p /btrfs_tmp/old_roots - timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/@root)" "+%Y-%m-%-d_%H:%M:%S") - mv /btrfs_tmp/@root "/btrfs_tmp/old_roots/$timestamp" - fi - - delete_subvolume_recursively() { - IFS=$'\n' - for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do - delete_subvolume_recursively "/btrfs_tmp/$i" - done - btrfs subvolume delete "$1" - } - - for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do - delete_subvolume_recursively "$i" - done - - btrfs subvolume create /btrfs_tmp/@root - umount /btrfs_tmp - ''; - }; -} diff --git a/hosts/desktops/io/hardware-configuration.nix b/hosts/desktops/io/hardware-configuration.nix deleted file mode 100644 index 037a503..0000000 --- a/hosts/desktops/io/hardware-configuration.nix +++ /dev/null @@ -1,83 +0,0 @@ -{ - config, - lib, - modulesPath, - ... -}: - -{ - imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - - boot = { - initrd = { - availableKernelModules = [ - "xhci_pci" - "ahci" - "usb_storage" - "sd_mod" - "sdhci_pci" - ]; - luks.devices."enc" = { - device = "/dev/disk/by-uuid/8018720e-42dd-453c-b374-adaa02eb48c9"; - keyFile = "/dev/disk/by-partuuid/cbc7e305-d32d-4250-b6ae-6a8264ea096e"; - }; - }; - kernelModules = [ "kvm-intel" ]; - }; - - fileSystems = { - "/" = { - device = "/dev/disk/by-uuid/3638cea6-5503-43cc-aa4f-3d37ebedad2f"; - fsType = "btrfs"; - options = [ - "subvol=@root" - "noatime" - "compress=zstd" - ]; - }; - "/home" = { - device = "/dev/disk/by-uuid/3638cea6-5503-43cc-aa4f-3d37ebedad2f"; - fsType = "btrfs"; - options = [ - "subvol=@home" - "noatime" - "compress=zstd" - ]; - }; - "/nix" = { - device = "/dev/disk/by-uuid/3638cea6-5503-43cc-aa4f-3d37ebedad2f"; - fsType = "btrfs"; - options = [ - "subvol=@nix" - "noatime" - "compress=zstd" - ]; - }; - "/persistent" = { - device = "/dev/disk/by-uuid/3638cea6-5503-43cc-aa4f-3d37ebedad2f"; - fsType = "btrfs"; - options = [ - "subvol=@persistent" - "noatime" - "compress=zstd" - ]; - }; - "/boot/efi" = { - device = "/dev/disk/by-uuid/31C9-08FF"; - fsType = "vfat"; - options = [ - "noatime" - "fmask=0077" - "dmask=0077" - ]; - }; - }; - - powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; - - networking.useDHCP = lib.mkDefault true; - - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; -} diff --git a/hosts/desktops/rotterdam.nix b/hosts/desktops/rotterdam.nix deleted file mode 100644 index 9294f82..0000000 --- a/hosts/desktops/rotterdam.nix +++ /dev/null @@ -1,90 +0,0 @@ -{ pkgs, ... }: - -let - qubesnsh = pkgs.writeTextFile { - name = "qubes.nsh"; - text = "HD1f65535a1:EFI\\qubes\\grubx64.efi"; - }; - - reboot-into-qubes = pkgs.makeDesktopItem { - name = "reboot-into-qubes"; - icon = pkgs.fetchurl { - url = "https://raw.githubusercontent.com/vinceliuice/Qogir-icon-theme/31f267e1f5fd4e9596bfd78dfb41a03d3a9f33ee/src/scalable/apps/distributor-logo-qubes.svg"; - sha256 = "sha256-QbHr7s5Wcs7uFtfqZctMyS0iDbMfiiZOKy2nHhDOfn0="; - }; - desktopName = "Qubes OS"; - genericName = "Reboot into Qubes OS"; - categories = [ "System" ]; - startupNotify = true; - exec = pkgs.writeShellScript "reboot-into-qubes" '' - ${pkgs.yad}/bin/yad --form \ - --title="Qubes OS" \ - --image distributor-logo-qubes \ - --text "Are you sure you want to reboot into Qubes OS?" \ - --button="Yes:0" --button="Cancel:1" - if [ $? -eq 0 ]; then - systemctl reboot --boot-loader-entry=qubes.conf - fi - ''; - }; -in -{ - imports = [ - # Host-common imports - ../common - # Desktop-common imports - ./common - # Host-specific imports - ./rotterdam - ]; - - networking.hostName = "rotterdam"; - - services = { - flatpak.packages = [ "net.retrodeck.retrodeck" ]; - keyd = { - enable = true; - keyboards.main = { - ids = [ "5653:0001" ]; - settings.main = { - esc = "overload(meta, esc)"; - }; - }; - }; - }; - - environment.systemPackages = with pkgs; [ reboot-into-qubes ]; - - # hardware.graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ]; - - systemd.targets.hibernate.enable = false; # disable non-functional hibernate - - nix.nixPath = [ "nixos-config=${./rotterdam.nix}" ]; - - boot = { - kernelParams = [ - "processor.max_cstate=1" # Fixes bug where ryzen cpus freeze when in highest C state - "clearcpuid=514" - # Fixes amdgpu freezing - "amdgpu.noretry=0" - "amdgpu.ppfeaturemask=0xfffd3fff" - "amdgpu.gpu_recovery=1" - "amdgpu.lockup_timeout=1000" - ]; - # QubesOS boot entry - loader.systemd-boot = { - extraFiles = { - "efi/edk2-shell/shell.efi" = "${pkgs.edk2-uefi-shell}/shell.efi"; - "qubes.nsh" = qubesnsh; - }; - extraEntries."qubes.conf" = '' - title Qubes OS - efi /efi/edk2-shell/shell.efi - options -nointerrupt qubes.nsh - sort-key ab - ''; - }; - }; - - programs.steam.dedicatedServer.openFirewall = true; -} diff --git a/hosts/desktops/rotterdam/default.nix b/hosts/desktops/rotterdam/default.nix deleted file mode 100644 index eedd2b4..0000000 --- a/hosts/desktops/rotterdam/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: - -{ - imports = [ - ./hardware-configuration.nix - ./ephermal.nix - ]; -} diff --git a/hosts/desktops/rotterdam/ephermal.nix b/hosts/desktops/rotterdam/ephermal.nix deleted file mode 100644 index 8161a99..0000000 --- a/hosts/desktops/rotterdam/ephermal.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ ... }: - -{ - boot.initrd.systemd.services.recreate-root = { - description = "Rolling over and creating new filesystem root"; - requires = [ "initrd-root-device.target" ]; - after = [ - "local-fs-pre.target" - "initrd-root-device.target" - ]; - requiredBy = [ "initrd-root-fs.target" ]; - before = [ "sysroot.mount" ]; - unitConfig = { - AssertPathExists = "/etc/initrd-release"; - DefaultDependencies = false; - }; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - script = '' - mkdir /btrfs_tmp - mount /dev/disk/by-uuid/3287dbc3-c0fa-4096-a0b3-59b017cfecc8 /btrfs_tmp - - if [[ -e /btrfs_tmp/@root ]]; then - mkdir -p /btrfs_tmp/old_roots - timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/@root)" "+%Y-%m-%-d_%H:%M:%S") - mv /btrfs_tmp/@root "/btrfs_tmp/old_roots/$timestamp" - fi - - delete_subvolume_recursively() { - IFS=$'\n' - for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do - delete_subvolume_recursively "/btrfs_tmp/$i" - done - btrfs subvolume delete "$1" - } - - for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do - delete_subvolume_recursively "$i" - done - - btrfs subvolume create /btrfs_tmp/@root - umount /btrfs_tmp - ''; - }; -} diff --git a/hosts/io/boot.nix b/hosts/io/boot.nix new file mode 100644 index 0000000..326f7dc --- /dev/null +++ b/hosts/io/boot.nix @@ -0,0 +1,14 @@ +{ + boot = { + # TODO check if future kernel versions fix boot issue with systemd initrd with tpm + initrd.systemd.tpm2.enable = false; + kernelParams = [ + "nosgx" + "i915.fastboot=1" + "mem_sleep_default=deep" + ]; + extraModprobeConfig = '' + options snd-intel-dspcfg dsp_driver=3 + ''; + }; +} diff --git a/hosts/io/disko.nix b/hosts/io/disko.nix new file mode 100644 index 0000000..4e6c9d5 --- /dev/null +++ b/hosts/io/disko.nix @@ -0,0 +1,79 @@ +{ inputs, ... }: + +{ + imports = [ inputs.disko.nixosModules.default ]; + + disko.devices.disk.main = { + type = "disk"; + device = "/dev/disk/by-id/mmc-hDEaP3_0x1041b689"; + content = { + type = "gpt"; + partitions = { + ESP = { + priority = 1; + name = "ESP"; + start = "1MiB"; + end = "1GiB"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot/efi"; + mountOptions = [ + "noatime" + "fmask=0077" + "dmask=0077" + ]; + }; + }; + cryptroot = { + priority = 2; + name = "root"; + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "@root" = { + mountpoint = "/"; + mountOptions = [ + "noatime" + "compress=zstd" + "subvol=@root" + ]; + }; + "@home" = { + mountpoint = "/home"; + mountOptions = [ + "noatime" + "compress=zstd" + "subvol=@home" + ]; + }; + "@nix" = { + mountpoint = "/nix"; + mountOptions = [ + "noatime" + "compress=zstd" + "subvol=@nix" + ]; + }; + "@persistent" = { + mountpoint = "/persistent"; + mountOptions = [ + "noatime" + "compress=zstd" + "subvol=@persistent" + ]; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/io/hardware-configuration.nix b/hosts/io/hardware-configuration.nix new file mode 100644 index 0000000..8e4dae4 --- /dev/null +++ b/hosts/io/hardware-configuration.nix @@ -0,0 +1,37 @@ +{ + config, + lib, + modulesPath, + inputs, + ... +}: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot = { + initrd = { + availableKernelModules = [ + "xhci_pci" + "ahci" + "usb_storage" + "sd_mod" + "sdhci_pci" + ]; + }; + kernelModules = [ "kvm-intel" ]; + }; + + zramSwap = { + enable = true; + memoryPercent = 100; + }; + + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + + networking.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/io/programs.nix b/hosts/io/programs.nix new file mode 100644 index 0000000..e272d22 --- /dev/null +++ b/hosts/io/programs.nix @@ -0,0 +1,27 @@ +{ pkgs, ... }: + +let + cml-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs { + wttsrc = pkgs.fetchFromGitHub { + owner = "WeirdTreeThing"; + repo = "chromebook-ucm-conf"; + rev = "b6ce2a7"; + hash = "sha256-QRUKHd3RQmg1tnZU8KCW0AmDtfw/daOJ/H3XU5qWTCc="; + }; + postInstall = '' + echo "v0.4.1" > $out/chromebook.patched + cp -R $wttsrc/{common,codecs,platforms} $out/share/alsa/ucm2 + cp -R $wttsrc/{cml,sof-rt5682} $out/share/alsa/ucm2/conf.d + ''; + }; +in + +{ + environment = { + systemPackages = with pkgs; [ + maliit-keyboard + sof-firmware + ]; + sessionVariables.ALSA_CONFIG_UCM2 = "${cml-ucm-conf}/share/alsa/ucm2"; + }; +} diff --git a/hosts/desktops/io.nix b/hosts/io/services.nix similarity index 51% rename from hosts/desktops/io.nix rename to hosts/io/services.nix index 1839968..df41a6f 100644 --- a/hosts/desktops/io.nix +++ b/hosts/io/services.nix @@ -1,67 +1,6 @@ { pkgs, ... }: -let - cml-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs { - wttsrc = pkgs.fetchFromGitHub { - owner = "WeirdTreeThing"; - repo = "chromebook-ucm-conf"; - rev = "b6ce2a7"; - hash = "sha256-QRUKHd3RQmg1tnZU8KCW0AmDtfw/daOJ/H3XU5qWTCc="; - }; - postInstall = '' - echo "v0.4.1" > $out/chromebook.patched - cp -R $wttsrc/{common,codecs,platforms} $out/share/alsa/ucm2 - cp -R $wttsrc/{cml,sof-rt5682} $out/share/alsa/ucm2/conf.d - ''; - }; -in { - imports = [ - # Host-common imports - ../common - # Desktop-common imports - ./common - # Host-specific imports - ./io - ]; - - networking.hostName = "io"; - - nix.nixPath = [ "nixos-config=${./io.nix}" ]; - - zramSwap = { - enable = true; - memoryPercent = 100; - }; - - boot = { - # TODO check if future kernel versions fix boot issue with systemd initrd with tpm - initrd.systemd.tpm2.enable = false; - kernelParams = [ - "nosgx" - "i915.fastboot=1" - "mem_sleep_default=deep" - ]; - extraModprobeConfig = '' - options snd-intel-dspcfg dsp_driver=3 - ''; - }; - - environment = { - systemPackages = with pkgs; [ - maliit-keyboard - sof-firmware - ]; - sessionVariables.ALSA_CONFIG_UCM2 = "${cml-ucm-conf}/share/alsa/ucm2"; - }; - - # TODO: remove once gmodena/nix-flatpak/issues/45 fixed - systemd.services."flatpak-managed-install" = { - serviceConfig = { - ExecStartPre = "${pkgs.coreutils}/bin/sleep 5"; - }; - }; - services = { keyd = { enable = true; @@ -100,7 +39,7 @@ in f9 = "f10"; f10 = "f11"; f13 = "f12"; - u = "sysrq"; + y = "sysrq"; k = "home"; l = "pageup"; "," = "end"; @@ -109,5 +48,14 @@ in }; }; }; + upower.enable = true; + power-profiles-daemon.enable = true; + }; + + # TODO: remove once gmodena/nix-flatpak/issues/45 fixed + systemd.services."flatpak-managed-install" = { + serviceConfig = { + ExecStartPre = "${pkgs.coreutils}/bin/sleep 5"; + }; }; } diff --git a/hosts/modules/ai.nix b/hosts/modules/ai.nix new file mode 100644 index 0000000..e2dd9d2 --- /dev/null +++ b/hosts/modules/ai.nix @@ -0,0 +1,10 @@ +{ inputs, pkgs, ... }: + +{ + environment.systemPackages = with inputs.nix-ai-tools.packages.${pkgs.system}; [ + claude-desktop + claude-code + claudebox + opencode + ]; +} diff --git a/hosts/modules/bluetooth.nix b/hosts/modules/bluetooth.nix new file mode 100644 index 0000000..fb6a06a --- /dev/null +++ b/hosts/modules/bluetooth.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + hardware.bluetooth.enable = true; +} diff --git a/hosts/common/boot.nix b/hosts/modules/common/boot.nix similarity index 95% rename from hosts/common/boot.nix rename to hosts/modules/common/boot.nix index 651c90c..fbba278 100644 --- a/hosts/common/boot.nix +++ b/hosts/modules/common/boot.nix @@ -1,4 +1,4 @@ -{ ... }: +{ pkgs, ... }: { boot = { diff --git a/hosts/common/console.nix b/hosts/modules/common/console.nix similarity index 100% rename from hosts/common/console.nix rename to hosts/modules/common/console.nix diff --git a/hosts/common/networking.nix b/hosts/modules/common/firewall.nix similarity index 65% rename from hosts/common/networking.nix rename to hosts/modules/common/firewall.nix index fdb6378..910e803 100644 --- a/hosts/common/networking.nix +++ b/hosts/modules/common/firewall.nix @@ -2,7 +2,7 @@ { networking = { - networkmanager.enable = true; firewall.enable = true; + nftables.enable = true; }; } diff --git a/hosts/common/locale.nix b/hosts/modules/common/locale.nix similarity index 93% rename from hosts/common/locale.nix rename to hosts/modules/common/locale.nix index 7e07d85..1171a32 100644 --- a/hosts/common/locale.nix +++ b/hosts/modules/common/locale.nix @@ -7,6 +7,7 @@ defaultLocale = "en_US.UTF-8"; extraLocaleSettings = { LC_ADDRESS = "pt_BR.utf8"; + LC_COLLATE = "pt_BR.utf8"; LC_IDENTIFICATION = "pt_BR.utf8"; LC_MEASUREMENT = "pt_BR.utf8"; LC_MONETARY = "pt_BR.utf8"; diff --git a/hosts/common/nix.nix b/hosts/modules/common/nix.nix similarity index 72% rename from hosts/common/nix.nix rename to hosts/modules/common/nix.nix index 4253f7b..5ef9c4c 100644 --- a/hosts/common/nix.nix +++ b/hosts/modules/common/nix.nix @@ -1,6 +1,8 @@ -{ ... }: +{ inputs, ... }: { + imports = [ inputs.nixos-cli.nixosModules.nixos-cli ]; + nix = { settings = { auto-optimise-store = true; @@ -24,5 +26,13 @@ buildDocs = false; }; + services.nixos-cli = { + enable = true; + config = { + use_nvd = true; + ignore_dirty_tree = true; + }; + }; + system.stateVersion = "22.11"; } diff --git a/hosts/modules/common/openssh.nix b/hosts/modules/common/openssh.nix new file mode 100644 index 0000000..df70bdd --- /dev/null +++ b/hosts/modules/common/openssh.nix @@ -0,0 +1,11 @@ +{ ... }: + +{ + services.openssh = { + enable = true; + settings.PermitRootLogin = "no"; + extraConfig = '' + PrintLastLog no + ''; + }; +} diff --git a/hosts/modules/common/programs.nix b/hosts/modules/common/programs.nix new file mode 100644 index 0000000..fd10953 --- /dev/null +++ b/hosts/modules/common/programs.nix @@ -0,0 +1,40 @@ +{ lib, pkgs, ... }: + +{ + environment = { + systemPackages = with pkgs; [ + ### Dev Tools ### + git + ### System Utilities ### + btop + fastfetch + helix + nixos-firewall-tool + nvd + sysz + tmux + wget + yazi + ]; + shellAliases = { + cat = "${lib.getExe pkgs.bat} --paging=never --style=plain"; + ls = "${lib.getExe pkgs.eza} --icons --group-directories-first"; + tree = "ls --tree"; + }; + }; + + programs = { + command-not-found.enable = false; + fish = { + enable = true; + interactiveShellInit = '' + set fish_greeting + if set -q SSH_CONNECTION + export TERM=xterm-256color + clear + fastfetch + end + ''; + }; + }; +} diff --git a/hosts/common/security.nix b/hosts/modules/common/security.nix similarity index 100% rename from hosts/common/security.nix rename to hosts/modules/common/security.nix diff --git a/hosts/modules/common/services.nix b/hosts/modules/common/services.nix new file mode 100644 index 0000000..89ac527 --- /dev/null +++ b/hosts/modules/common/services.nix @@ -0,0 +1,9 @@ +{ ... }: + +{ + services = { + dbus.implementation = "broker"; + irqbalance.enable = true; + fstrim.enable = true; + }; +} diff --git a/hosts/modules/common/tailscale.nix b/hosts/modules/common/tailscale.nix new file mode 100644 index 0000000..98bea97 --- /dev/null +++ b/hosts/modules/common/tailscale.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + services.tailscale = { + enable = true; + extraUpFlags = [ "--operator=user" ]; + }; +} diff --git a/hosts/common/users.nix b/hosts/modules/common/users.nix similarity index 58% rename from hosts/common/users.nix rename to hosts/modules/common/users.nix index 41d2253..7dd6490 100644 --- a/hosts/common/users.nix +++ b/hosts/modules/common/users.nix @@ -7,21 +7,17 @@ shell = pkgs.fish; extraGroups = [ "networkmanager" - "docker" "wheel" ]; openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcwF1yuWEfYGScNocEbs0AmGxyTIzGc4/IhpU587SJE" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICQPkAyy+Du9Omc2WtnUF2TV8jFAF4H6mJi2D4IZ1nzg user@himalia" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3Y0PVpGfJHonqDS7qoCFhqzUvqGq9I9sax+F9e/5cs user@io" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL user@rotterdam" ]; hashedPassword = "$6$Pj7v/CpstyuWQQV0$cNujVDhfMBdwlGVEnnd8t71.kZPixbo0u25cd.874iaqLTH4V5fa1f98V5zGapjQCz5JyZmsR94xi00sUrntT0"; }; root = { shell = pkgs.fish; - openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcwF1yuWEfYGScNocEbs0AmGxyTIzGc4/IhpU587SJE" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL" - ]; hashedPassword = "!"; }; }; diff --git a/hosts/desktops/common/boot.nix b/hosts/modules/desktop/boot.nix similarity index 100% rename from hosts/desktops/common/boot.nix rename to hosts/modules/desktop/boot.nix diff --git a/hosts/modules/desktop/desktop.nix b/hosts/modules/desktop/desktop.nix new file mode 100644 index 0000000..03ec04b --- /dev/null +++ b/hosts/modules/desktop/desktop.nix @@ -0,0 +1,163 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +{ + imports = [ + inputs.niri-flake.nixosModules.niri + inputs.nix-flatpak.nixosModules.nix-flatpak + ]; + + environment = { + sessionVariables = { + KDEHOME = "$XDG_CONFIG_HOME/kde4"; # Stops kde from placing a .kde4 folder in the home dir + NIXOS_OZONE_WL = "1"; # Forces chromium and most electron apps to run in wayland + }; + systemPackages = with pkgs; [ + ### Web ### + bitwarden-desktop + fragments + nextcloud-client + tor-browser + vesktop + inputs.zen-browser.packages."${system}".default + ### Office & Productivity ### + aspell + aspellDicts.de + aspellDicts.en + aspellDicts.en-computers + aspellDicts.pt_BR + libreoffice + onlyoffice-desktopeditors + papers + presenterm + rnote + ### Graphics & Design ### + gimp + inkscape + plasticity + ### System Utilities ### + adwaita-icon-theme + ghostty + gnome-disk-utility + junction + libfido2 + mission-center + nautilus + p7zip + rclone + toggleaudiosink + unrar + ### Media ### + decibels + loupe + obs-studio + showtime + ]; + }; + + services = { + pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + jack.enable = true; + wireplumber.enable = true; + }; + greetd = { + enable = true; + settings = { + default_session = { + command = "${lib.getExe pkgs.tuigreet} --user-menu --time --remember --asterisks --cmd ${config.programs.niri.package}/bin/niri-session"; + user = "greeter"; + }; + } + // lib.optionalAttrs (config.networking.hostName == "io") { + initial_session = { + command = "${config.programs.niri.package}/bin/niri-session"; + user = "user"; + }; + }; + }; + flatpak = { + enable = true; + packages = [ + ### Graphics & Design ### + "com.boxy_svg.BoxySVG" + rec { + appId = "io.github.softfever.OrcaSlicer"; + sha256 = "0hdx5sg6fknj1pfnfxvlfwb5h6y1vjr6fyajbsnjph5gkp97c6p1"; + bundle = "${pkgs.fetchurl { + url = "https://github.com/SoftFever/OrcaSlicer/releases/download/v2.3.0/OrcaSlicer-Linux-flatpak_V2.3.0_x86_64.flatpak"; + inherit sha256; + }}"; + } + ### System Utilities ### + "com.github.tchx84.Flatseal" + "com.rustdesk.RustDesk" + ]; + uninstallUnmanaged = true; + update.auto.enable = true; + }; + gvfs.enable = true; + }; + + security.rtkit.enable = true; # Needed for pipewire to acquire realtime priority + + users = { + users.greeter = { + isSystemUser = true; + group = "greeter"; + }; + groups.greeter = { }; + }; + + programs = { + niri = { + enable = true; + package = inputs.niri.packages.${pkgs.system}.niri; + }; + kdeconnect = { + enable = true; + package = pkgs.valent; + }; + dconf.enable = true; + appimage = { + enable = true; + binfmt = true; + }; + }; + + niri-flake.cache.enable = false; + + fonts = { + fontDir.enable = true; + packages = with pkgs; [ + corefonts + inter + nerd-fonts.fira-code + noto-fonts-cjk-sans + noto-fonts-color-emoji + roboto + ]; + }; + + xdg.portal = { + extraPortals = with pkgs; [ + xdg-desktop-portal-gnome + xdg-desktop-portal-gtk + ]; + config = { + common.default = "*"; + niri.default = [ + "gtk" + "gnome" + ]; + }; + }; +} diff --git a/hosts/desktops/common/nix.nix b/hosts/modules/desktop/nix.nix similarity index 100% rename from hosts/desktops/common/nix.nix rename to hosts/modules/desktop/nix.nix diff --git a/hosts/common/services.nix b/hosts/modules/desktop/services.nix similarity index 50% rename from hosts/common/services.nix rename to hosts/modules/desktop/services.nix index 2cfb61e..66b78f1 100644 --- a/hosts/common/services.nix +++ b/hosts/modules/desktop/services.nix @@ -1,14 +1,9 @@ -{ ... }: +{ pkgs, ... }: { services = { - fwupd.enable = true; - fstrim.enable = true; - tailscale = { - enable = true; - extraUpFlags = [ "--operator=user" ]; - }; - openssh.enable = true; + printing.enable = true; + udev.packages = with pkgs; [ yubikey-personalization ]; keyd = { enable = true; keyboards.all = { diff --git a/hosts/modules/dev.nix b/hosts/modules/dev.nix new file mode 100644 index 0000000..c4cca78 --- /dev/null +++ b/hosts/modules/dev.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: + +{ + environment.systemPackages = with pkgs; [ + bat + lazygit + fd + fzf + glow + nixfmt-rfc-style + nix-init + nix-output-monitor + ripgrep + ]; + + programs.adb.enable = true; + + users.users.user.extraGroups = [ "adbusers" ]; +} diff --git a/hosts/desktops/common/impermanence.nix b/hosts/modules/ephemeral.nix similarity index 52% rename from hosts/desktops/common/impermanence.nix rename to hosts/modules/ephemeral.nix index d1ceacc..cad5f41 100644 --- a/hosts/desktops/common/impermanence.nix +++ b/hosts/modules/ephemeral.nix @@ -1,6 +1,21 @@ -{ ... }: +{ config, inputs, ... }: { + imports = [ + inputs.impermanence.nixosModules.impermanence + inputs.self.nixosModules.ephemeral + ]; + + ephemeral = { + enable = true; + rootDevice = + if config.networking.hostName == "trantor" then + "/dev/disk/by-id/scsi-360b207ed25d84372a95d1ecf842f8e20-part2" + else + "/dev/mapper/cryptroot"; + rootSubvolume = "@root"; + }; + environment.persistence.main = { persistentStoragePath = "/persistent"; files = [ @@ -11,13 +26,16 @@ "/etc/ssh/ssh_host_rsa_key.pub" ]; directories = [ - "/var/log" - "/var/lib/bluetooth" - "/var/lib/nixos" - "/var/lib/flatpak" - "/var/lib/tailscale" - "/var/lib/systemd/coredump" "/etc/NetworkManager/system-connections" + "/etc/nixos" + "/var/lib/bluetooth" + "/var/lib/flatpak" + "/var/lib/lxd" + "/var/lib/nixos" + "/var/lib/systemd/coredump" + "/var/lib/systemd/timers" + "/var/lib/tailscale" + "/var/log" ]; }; } diff --git a/hosts/modules/fwupd.nix b/hosts/modules/fwupd.nix new file mode 100644 index 0000000..52dc13e --- /dev/null +++ b/hosts/modules/fwupd.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + services.fwupd.enable = true; +} diff --git a/hosts/modules/gaming.nix b/hosts/modules/gaming.nix new file mode 100644 index 0000000..5aef14e --- /dev/null +++ b/hosts/modules/gaming.nix @@ -0,0 +1,35 @@ +{ pkgs, ... }: + +{ + environment.systemPackages = with pkgs; [ + clonehero + heroic + mangohud + prismlauncher + steam-run + ]; + + programs = { + steam = { + enable = true; + extraCompatPackages = [ pkgs.proton-ge-bin ]; + }; + gamemode.enable = true; + }; + + hardware = { + xpadneo.enable = true; + steam-hardware.enable = true; # Allow steam client to manage controllers + graphics.enable32Bit = true; # For OpenGL games + }; + + services.flatpak.packages = [ + "com.github.k4zmu2a.spacecadetpinball" + "com.steamgriddb.SGDBoop" + "io.github.Foldex.AdwSteamGtk" + "io.itch.itch" + "io.mrarm.mcpelauncher" + "net.retrodeck.retrodeck" + "org.freedesktop.Platform.VulkanLayer.MangoHud/x86_64/24.08" + ]; +} diff --git a/hosts/modules/libvirtd.nix b/hosts/modules/libvirtd.nix new file mode 100644 index 0000000..41cfa27 --- /dev/null +++ b/hosts/modules/libvirtd.nix @@ -0,0 +1,12 @@ +{ ... }: + +{ + virtualisation.libvirtd.enable = true; + + programs.virt-manager.enable = true; + + users.users.user.extraGroups = [ + "libvirt" + "libvirtd" + ]; +} diff --git a/hosts/modules/networkmanager.nix b/hosts/modules/networkmanager.nix new file mode 100644 index 0000000..7634116 --- /dev/null +++ b/hosts/modules/networkmanager.nix @@ -0,0 +1,10 @@ +{ ... }: + +{ + networking.networkmanager = { + enable = true; + wifi.backend = "iwd"; + }; + + users.users.user.extraGroups = [ "networkmanager" ]; +} diff --git a/hosts/common/virtualisation.nix b/hosts/modules/podman.nix similarity index 91% rename from hosts/common/virtualisation.nix rename to hosts/modules/podman.nix index 1235555..99018cc 100644 --- a/hosts/common/virtualisation.nix +++ b/hosts/modules/podman.nix @@ -3,7 +3,6 @@ { virtualisation.podman = { enable = true; - dockerCompat = true; autoPrune.enable = true; extraPackages = [ pkgs.podman-compose ]; }; diff --git a/hosts/servers/common/boot.nix b/hosts/modules/server/boot.nix similarity index 100% rename from hosts/servers/common/boot.nix rename to hosts/modules/server/boot.nix diff --git a/hosts/servers/common/nix.nix b/hosts/modules/server/nix.nix similarity index 100% rename from hosts/servers/common/nix.nix rename to hosts/modules/server/nix.nix diff --git a/hosts/servers/common/services.nix b/hosts/modules/server/tailscale.nix similarity index 55% rename from hosts/servers/common/services.nix rename to hosts/modules/server/tailscale.nix index 035de35..1f105ba 100644 --- a/hosts/servers/common/services.nix +++ b/hosts/modules/server/tailscale.nix @@ -5,4 +5,9 @@ extraSetFlags = [ "--advertise-exit-node" ]; useRoutingFeatures = "server"; }; + + boot.kernel.sysctl = { + "net.ipv4.ip_forward" = 1; + "net.ipv6.conf.all.forwarding" = 1; + }; } diff --git a/hosts/rotterdam/boot.nix b/hosts/rotterdam/boot.nix new file mode 100644 index 0000000..d038ede --- /dev/null +++ b/hosts/rotterdam/boot.nix @@ -0,0 +1,31 @@ +{ pkgs, ... }: + +let + qubesnsh = pkgs.writeTextFile { + name = "qubes.nsh"; + text = "HD1f65535a1:EFI\\qubes\\grubx64.efi"; + }; +in + +{ + boot = { + kernelParams = [ + "processor.max_cstate=1" # Fixes bug where ryzen cpus freeze when in highest C state + "clearcpuid=514" + "amdgpu.ppfeaturemask=0xfffd3fff" # Fixes amdgpu freezing + ]; + # QubesOS boot entry + loader.systemd-boot = { + extraFiles = { + "efi/edk2-shell/shell.efi" = "${pkgs.edk2-uefi-shell}/shell.efi"; + "qubes.nsh" = qubesnsh; + }; + extraEntries."qubes.conf" = '' + title Qubes OS + efi /efi/edk2-shell/shell.efi + options -nointerrupt qubes.nsh + sort-key ab + ''; + }; + }; +} diff --git a/hosts/desktops/rotterdam/hardware-configuration.nix b/hosts/rotterdam/hardware-configuration.nix similarity index 88% rename from hosts/desktops/rotterdam/hardware-configuration.nix rename to hosts/rotterdam/hardware-configuration.nix index 524d0ab..169c53f 100644 --- a/hosts/desktops/rotterdam/hardware-configuration.nix +++ b/hosts/rotterdam/hardware-configuration.nix @@ -72,18 +72,8 @@ "compress=zstd" ]; }; - "/swap" = { - device = "/dev/disk/by-uuid/3287dbc3-c0fa-4096-a0b3-59b017cfecc8"; - fsType = "btrfs"; - options = [ - "subvol=@swap" - "noatime" - ]; - }; }; - swapDevices = [ { device = "/swap/swapfile"; } ]; - networking.useDHCP = lib.mkDefault true; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; diff --git a/hosts/rotterdam/hardware.nix b/hosts/rotterdam/hardware.nix new file mode 100644 index 0000000..6f76e99 --- /dev/null +++ b/hosts/rotterdam/hardware.nix @@ -0,0 +1,8 @@ +{ pkgs, ... }: + +{ + hardware = { + amdgpu.opencl.enable = true; + graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ]; + }; +} diff --git a/hosts/rotterdam/programs.nix b/hosts/rotterdam/programs.nix new file mode 100644 index 0000000..b4dcfd9 --- /dev/null +++ b/hosts/rotterdam/programs.nix @@ -0,0 +1,31 @@ +{ pkgs, ... }: + +let + reboot-into-qubes = pkgs.makeDesktopItem { + name = "reboot-into-qubes"; + icon = pkgs.fetchurl { + url = "https://raw.githubusercontent.com/vinceliuice/Qogir-icon-theme/31f267e1f5fd4e9596bfd78dfb41a03d3a9f33ee/src/scalable/apps/distributor-logo-qubes.svg"; + sha256 = "sha256-QbHr7s5Wcs7uFtfqZctMyS0iDbMfiiZOKy2nHhDOfn0="; + }; + desktopName = "Qubes OS"; + genericName = "Reboot into Qubes OS"; + categories = [ "System" ]; + startupNotify = true; + exec = pkgs.writeShellScript "reboot-into-qubes" '' + ${pkgs.yad}/bin/yad --form \ + --title="Qubes OS" \ + --image distributor-logo-qubes \ + --text "Are you sure you want to reboot into Qubes OS?" \ + --button="Yes:0" --button="Cancel:1" + if [ $? -eq 0 ]; then + systemctl reboot --boot-loader-entry=qubes.conf + fi + ''; + }; +in + +{ + environment.systemPackages = [ reboot-into-qubes ]; + + programs.steam.dedicatedServer.openFirewall = true; +} diff --git a/hosts/rotterdam/services.nix b/hosts/rotterdam/services.nix new file mode 100644 index 0000000..0bf276f --- /dev/null +++ b/hosts/rotterdam/services.nix @@ -0,0 +1,11 @@ +{ + services.keyd = { + enable = true; + keyboards.main = { + ids = [ "5653:0001" ]; + settings.main = { + esc = "overload(meta, esc)"; + }; + }; + }; +} diff --git a/hosts/servers/alexandria.nix b/hosts/servers/alexandria.nix deleted file mode 100644 index 4154097..0000000 --- a/hosts/servers/alexandria.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ ... }: - -{ - imports = [ - # Host-common imports - ../common - # Server-common imports - ./common - # Host-specific imports - ./alexandria - ]; - - nix.nixPath = [ "nixos-config=${./alexandria.nix}" ]; - - swapDevices = [ - { - device = "/swapfile"; - size = 8192; - } - ]; - - networking = { - hostName = "alexandria"; - firewall = { - allowedTCPPorts = [ - 80 - 443 - 8010 - 9666 - ]; - allowedUDPPorts = [ 24454 ]; - }; - }; -} diff --git a/hosts/servers/alexandria/changedetection.nix b/hosts/servers/alexandria/changedetection.nix deleted file mode 100644 index 702952f..0000000 --- a/hosts/servers/alexandria/changedetection.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ config, lib, ... }: - -{ - services = { - changedetection-io = { - enable = true; - behindProxy = true; - datastorePath = "/data/changedetection"; - port = lib.toInt "${config.ports.changedetection-io}"; - baseURL = "https://detect.baduhai.dev"; - }; - - nginx.virtualHosts."detect.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.changedetection-io}"; - }; - }; -} diff --git a/hosts/servers/alexandria/cinny.nix b/hosts/servers/alexandria/cinny.nix deleted file mode 100644 index fc4770f..0000000 --- a/hosts/servers/alexandria/cinny.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ config, ... }: - -{ - virtualisation.oci-containers.containers."cinny" = { - image = "ghcr.io/cinnyapp/cinny:latest"; - ports = [ "${config.ports.cinny}:80" ]; - environment = { - TZ = "America/Bahia"; - }; - volumes = [ "/data/matrix/cinny-config.json:/app/config.json" ]; - extraOptions = [ - "--pull=newer" - "--label=io.containers.autoupdate=registry" - ]; - }; - - services.nginx.virtualHosts."matrix.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.cinny}"; - }; -} diff --git a/hosts/servers/alexandria/default.nix b/hosts/servers/alexandria/default.nix deleted file mode 100644 index d5069a1..0000000 --- a/hosts/servers/alexandria/default.nix +++ /dev/null @@ -1,51 +0,0 @@ -{ lib, ... }: - -let - mkStringOption = - default: - lib.mkOption { - inherit default; - type = lib.types.str; - }; - -in - -{ - imports = [ - ./changedetection.nix - ./cinny.nix - ./forgejo.nix - ./hardware-configuration.nix - ./jellyfin.nix - ./librespeed.nix - ./memos.nix - ./minecraft.nix - ./nextcloud.nix - ./nginx.nix - ./paperless.nix - ./searx.nix - ./services.nix - ./users.nix - ./vaultwarden.nix - ]; - - options.ports = { - bazaar = mkStringOption "6767"; - radarr = mkStringOption "7878"; - vaultwarden = mkStringOption "8000"; - changedetection-io = mkStringOption "8001"; - cinny = mkStringOption "8002"; - librespeed = mkStringOption "8003"; - paperless = mkStringOption "8004"; - yousable = mkStringOption "8005"; - cinny2 = mkStringOption "8006"; - searx = mkStringOption "8007"; - qbittorrent = mkStringOption "8008"; - actual = mkStringOption "8009"; - memos = mkStringOption "8010"; - collabora = mkStringOption "8011"; - jellyfin = mkStringOption "8096"; - sonarr = mkStringOption "8989"; - jackett = mkStringOption "9117"; - }; -} diff --git a/hosts/servers/alexandria/forgejo.nix b/hosts/servers/alexandria/forgejo.nix deleted file mode 100644 index a51c050..0000000 --- a/hosts/servers/alexandria/forgejo.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ config, ... }: - -let - domain = "git.baduhai.dev"; -in - -{ - services = { - forgejo = { - enable = true; - repositoryRoot = "/data/forgejo"; - settings = { - session.COOKIE_SECURE = true; - server = { - PROTOCOL = "http+unix"; - DOMAIN = domain; - ROOT_URL = "https://${domain}"; - OFFLINE_MODE = true; # disable use of CDNs - SSH_DOMAIN = "baduhai.dev"; - }; - log.LEVEL = "Warn"; - mailer.ENABLED = false; - actions.ENABLED = false; - }; - }; - nginx.virtualHosts.${domain} = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/"; - }; - }; -} diff --git a/hosts/servers/alexandria/jellyfin.nix b/hosts/servers/alexandria/jellyfin.nix deleted file mode 100644 index 015f4aa..0000000 --- a/hosts/servers/alexandria/jellyfin.nix +++ /dev/null @@ -1,19 +0,0 @@ -{ config, ... }: - -{ - services = { - jellyfin = { - enable = true; - user = "user"; - group = "hosted"; - openFirewall = true; - }; - - nginx.virtualHosts."jellyfin.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.jellyfin}"; - }; - }; -} diff --git a/hosts/servers/alexandria/librespeed.nix b/hosts/servers/alexandria/librespeed.nix deleted file mode 100644 index 6b830b7..0000000 --- a/hosts/servers/alexandria/librespeed.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ config, ... }: - -{ - virtualisation.oci-containers.containers."librespeed" = { - image = "lscr.io/linuxserver/librespeed:latest"; - environment = { - TZ = "America/Bahia"; - }; - ports = [ "${config.ports.librespeed}:80" ]; - extraOptions = [ - "--pull=newer" - "--label=io.containers.autoupdate=registry" - ]; - }; - - services.nginx.virtualHosts."speed.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.librespeed}"; - }; -} diff --git a/hosts/servers/alexandria/memos.nix b/hosts/servers/alexandria/memos.nix deleted file mode 100644 index 2d41cc0..0000000 --- a/hosts/servers/alexandria/memos.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ config, ... }: - -{ - virtualisation.oci-containers.containers."memos" = { - image = "docker.io/neosmemo/memos:stable"; - ports = [ "${config.ports.memos}:5230" ]; - environment = { - TZ = "America/Bahia"; - }; - volumes = [ "/data/memos/:/var/opt/memos" ]; - extraOptions = [ - "--pull=newer" - "--label=io.containers.autoupdate=registry" - ]; - }; - - services.nginx.virtualHosts."notes.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.memos}"; - }; -} diff --git a/hosts/servers/alexandria/minecraft.nix b/hosts/servers/alexandria/minecraft.nix deleted file mode 100644 index 2ce951f..0000000 --- a/hosts/servers/alexandria/minecraft.nix +++ /dev/null @@ -1,73 +0,0 @@ -{ pkgs, ... }: - -{ - services.minecraft-servers = { - enable = true; - eula = true; - dataDir = "/data/minecraft"; - servers."kingdomcums" = { - enable = true; - package = pkgs.fabricServers.fabric-1_20_1; - openFirewall = true; - serverProperties = { - difficulty = "normal"; - gamemode = "survival"; - motd = "Kingdom Cums"; - online-mode = false; - spawn-protection = false; - }; - symlinks."mods" = pkgs.linkFarmFromDrvs "mods" ( - builtins.attrValues { - villagerNames = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/gqRXDo8B/versions/rzXhJ2pH/villagernames-1.20.1-8.1.jar"; - sha256 = "0hcbbp3zi3nnr12kian9l645f22jr7495bcrlbng46nxp9h08pg5"; - }; - lithium = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/gvQqBUqZ/versions/ZSNsJrPI/lithium-fabric-mc1.20.1-0.11.2.jar"; - sha256 = "1ycdvrs46bbdxsa6i38sfx70v47nvzzbmblfpy3hq3k8blsrbid0"; - }; - lootr = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/EltpO5cN/versions/fqmzdpE2/lootr-fabric-1.20-0.7.33.81.jar"; - sha256 = "0db0472rb07nbc9i925qp3n7s7nmrq6q3alhprflgc9gqg0j0f14"; - }; - malilib = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/GcWjdA9I/versions/V7yLDtJV/malilib-fabric-1.20.1-0.16.3.jar"; - sha256 = "129m1jnk58p0wid5fmagqx13wp6pw4gja01yx14aljdxgzr8kqas"; - }; - immersivePaintings = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/6txNkua3/versions/UjL11A4h/immersive_paintings-0.6.7%2B1.20.1-fabric.jar"; - sha256 = "1di9a67q372z6lplnsa1kmh86armya83mimn61c8ai7izjlsfnid"; - }; - entityCulling = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/NNAgCjsB/versions/mahLIqpj/entityculling-fabric-1.6.7-mc1.20.1.jar"; - sha256 = "01iz8rgljgzl0d8gcwpmr6wcvv3b0cf1siggp3dn8q5hv9przk9k"; - }; - fabricAPI = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/P7uGFii0/fabric-api-0.92.2%2B1.20.1.jar"; - sha256 = "1z3hcxng2p9ymph1c0k729vxxaasi34n6fcdsqwx0wsmqi2gh025"; - }; - fallingTree = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/Fb4jn8m6/versions/NrtzFkZE/FallingTree-1.20.1-4.3.4.jar"; - sha256 = "0sfv2laxzgmkhmr0kizi7g09r6fkccjhj9p5j0viqywnwx02r7fs"; - }; - carryOn = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/joEfVgkn/versions/Mkla4B3q/carryon-fabric-1.20.1-2.1.2.7.jar"; - sha256 = "1pgbqrjrxw7bgwn6phpywgpjfmf5h341ba93j76ibk649wbgn9cd"; - }; - collective = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/e0M1UDsY/versions/jo7YkyNS/collective-1.20.1-7.84.jar"; - sha256 = "01qvaqmd5kmxq7sins6703xq5ckc47qs5kd62gnjyfq1dbjp2y2b"; - }; - dynamicLights = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/7YjclEGc/versions/eU6PA0pr/dynamiclights-v1.8.3-mc1.17x-1.21x-mod.jar"; - sha256 = "0vdv525gis1vj514iqh4rbl6byp7k0ls3lsyj0c3db8g58d784gm"; - }; - appleSkin = pkgs.fetchurl { - url = "https://cdn.modrinth.com/data/EsAfCjCV/versions/xcauwnEB/appleskin-fabric-mc1.20.1-2.5.1.jar"; - sha256 = "1d9qmzjlk763ycmizqpmhcq0hhqw9j8hij6xk8p8l11ljr13mql5"; - }; - } - ); - }; - }; -} diff --git a/hosts/servers/alexandria/nginx.nix b/hosts/servers/alexandria/nginx.nix deleted file mode 100644 index 5075bcf..0000000 --- a/hosts/servers/alexandria/nginx.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ config, ... }: - -{ - services.nginx = { - enable = true; - group = "hosted"; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - }; - - security.acme = { - acceptTerms = true; - defaults = { - email = "baduhai@proton.me"; - dnsResolver = "1.1.1.1:53"; - dnsProvider = "cloudflare"; - credentialsFile = config.age.secrets.cloudflare.path; - }; - certs."baduhai.dev" = { - extraDomainNames = [ "*.baduhai.dev" ]; - }; - }; - - boot.kernel.sysctl = { - "net.ipv4.ip_forward" = 1; - "net.ipv6.conf.all.forwarding" = 1; - }; - - age.secrets.cloudflare = { - file = ../../../secrets/cloudflare.age; - owner = "nginx"; - group = "hosted"; - }; - -} diff --git a/hosts/servers/alexandria/paperless.nix b/hosts/servers/alexandria/paperless.nix deleted file mode 100644 index d78d107..0000000 --- a/hosts/servers/alexandria/paperless.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ config, lib, ... }: - -{ - services = { - paperless = { - enable = true; - dataDir = "/data/paperless/data"; - mediaDir = "/data/paperless/media"; - passwordFile = config.age.secrets.paperless.path; - port = lib.toInt "${config.ports.paperless}"; - consumptionDirIsPublic = true; - settings = { - PAPERLESS_OCR_LANGUAGE = "eng+por+deu"; - }; - }; - - nginx.virtualHosts."docs.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.paperless}"; - }; - }; - - age.secrets.paperless = { - file = ../../../secrets/paperless.age; - owner = "paperless"; - group = "hosted"; - }; -} diff --git a/hosts/servers/alexandria/searx.nix b/hosts/servers/alexandria/searx.nix deleted file mode 100644 index 94f3017..0000000 --- a/hosts/servers/alexandria/searx.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: - -{ - services = { - searx = { - enable = true; - package = pkgs.searxng; - settings.server = { - port = lib.toInt "${config.ports.searx}"; - bind_address = "0.0.0.0"; - secret_key = "&yEf!xLA@y3FdJ5BjKnUnNAkqer$iW!9"; - method = "GET"; - }; - }; - - nginx.virtualHosts."search.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.searx}"; - }; - }; -} diff --git a/hosts/servers/alexandria/services.nix b/hosts/servers/alexandria/services.nix deleted file mode 100644 index 08b927a..0000000 --- a/hosts/servers/alexandria/services.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ ... }: - -{ - services.postgresql.enable = true; - - # TODO: remove when bug fux - # Workaround for upstream bug in NetworkManager-wait-online.service - systemd.services.NetworkManager-wait-online.enable = false; -} diff --git a/hosts/servers/alexandria/users.nix b/hosts/servers/alexandria/users.nix deleted file mode 100644 index db3f3ed..0000000 --- a/hosts/servers/alexandria/users.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ ... }: - -{ - users = { - users = { - nginx.extraGroups = [ "acme" ]; - }; - groups = { - hosted = { - gid = 1005; - members = [ - "user" - "minecraft" - "paperless" - "vaultwarden" - ]; - }; - }; - }; -} diff --git a/hosts/servers/alexandria/vaultwarden.nix b/hosts/servers/alexandria/vaultwarden.nix deleted file mode 100644 index 2207c08..0000000 --- a/hosts/servers/alexandria/vaultwarden.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ config, ... }: - -{ - services = { - vaultwarden = { - enable = true; - config = { - DOMAIN = "https://pass.baduhai.dev"; - SIGNUPS_ALLOWED = true; - ROCKET_ADDRESS = "127.0.0.1"; - ROCKET_PORT = "${config.ports.vaultwarden}"; - }; - }; - - nginx.virtualHosts."pass.baduhai.dev" = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://127.0.0.1:${config.ports.vaultwarden}"; - }; - }; -} diff --git a/hosts/servers/common/default.nix b/hosts/servers/common/default.nix deleted file mode 100644 index db2cb46..0000000 --- a/hosts/servers/common/default.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./home-manager.nix - ./nix.nix - ./services.nix - ]; -} diff --git a/hosts/servers/common/home-manager.nix b/hosts/servers/common/home-manager.nix deleted file mode 100644 index 20186df..0000000 --- a/hosts/servers/common/home-manager.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ ... }: - -{ - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - backupFileExtension = "bkp"; - users.user = import ../../../users/servers/user.nix; - }; -} diff --git a/hosts/trantor/boot.nix b/hosts/trantor/boot.nix new file mode 100644 index 0000000..0498818 --- /dev/null +++ b/hosts/trantor/boot.nix @@ -0,0 +1,6 @@ +{ + boot = { + initrd.systemd.enable = true; + loader.efi.efiSysMountPoint = "/boot/efi"; + }; +} diff --git a/hosts/trantor/disko.nix b/hosts/trantor/disko.nix new file mode 100644 index 0000000..0e47058 --- /dev/null +++ b/hosts/trantor/disko.nix @@ -0,0 +1,64 @@ +{ inputs, ... }: + +{ + imports = [ inputs.disko.nixosModules.default ]; + + disko.devices.disk.main = { + type = "disk"; + device = "/dev/disk/by-id/scsi-360b207ed25d84372a95d1ecf842f8e20"; + content = { + type = "gpt"; + partitions = { + ESP = { + priority = 1; + name = "ESP"; + start = "1MiB"; + end = "512MiB"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot/efi"; + mountOptions = [ + "noatime" + "fmask=0077" + "dmask=0077" + ]; + }; + }; + root = { + priority = 2; + name = "root"; + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "@root" = { + mountpoint = "/"; + mountOptions = [ + "noatime" + "compress=zstd" + ]; + }; + "@nix" = { + mountpoint = "/nix"; + mountOptions = [ + "noatime" + "compress=zstd" + ]; + }; + "@persistent" = { + mountpoint = "/persistent"; + mountOptions = [ + "noatime" + "compress=zstd" + ]; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/trantor/fail2ban.nix b/hosts/trantor/fail2ban.nix new file mode 100644 index 0000000..bc05139 --- /dev/null +++ b/hosts/trantor/fail2ban.nix @@ -0,0 +1,23 @@ +{ config, pkgs, ... }: + +{ + services.fail2ban = { + enable = true; + maxretry = 5; + ignoreIP = [ + "127.0.0.0/8" + "::1" + "10.0.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + "100.64.0.0/10" + ]; + bantime = "1h"; + bantime-increment = { + enable = true; + multipliers = "1 2 4 8 16 32 64"; + maxtime = "10000h"; + overalljails = true; + }; + }; +} diff --git a/hosts/trantor/forgejo.nix b/hosts/trantor/forgejo.nix new file mode 100644 index 0000000..fdfa64a --- /dev/null +++ b/hosts/trantor/forgejo.nix @@ -0,0 +1,72 @@ +{ + config, + lib, + inputs, + ... +}: + +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts; +in + +{ + services = { + forgejo = { + enable = true; + settings = { + session.COOKIE_SECURE = true; + server = { + PROTOCOL = "http+unix"; + DOMAIN = "git.baduhai.dev"; + ROOT_URL = "https://git.baduhai.dev"; + OFFLINE_MODE = true; # disable use of CDNs + SSH_DOMAIN = "git.baduhai.dev"; + }; + log.LEVEL = "Warn"; + mailer.ENABLED = false; + actions.ENABLED = false; + service.DISABLE_REGISTRATION = true; + oauth2_client = { + ENABLE_AUTO_REGISTRATION = true; + UPDATE_AVATAR = true; + ACCOUNT_LINKING = "login"; + USERNAME = "preferred_username"; + }; + }; + }; + nginx.virtualHosts = mkNginxVHosts { + domains."git.baduhai.dev".locations."/".proxyPass = + "http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/"; + }; + fail2ban.jails.forgejo = { + settings = { + enabled = true; + filter = "forgejo"; + maxretry = 3; + findtime = "10m"; + bantime = "1h"; + }; + }; + }; + + environment = { + etc."fail2ban/filter.d/forgejo.conf".text = '' + [Definition] + failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from + ignoreregex = + journalmatch = _SYSTEMD_UNIT=forgejo.service + ''; + + persistence.main.directories = [ + { + directory = config.services.forgejo.stateDir; + inherit (config.services.forgejo) user group; + mode = "0700"; + } + ]; + }; + + # Disable PrivateMounts to allow LoadCredential to work with bind-mounted directories + systemd.services.forgejo.serviceConfig.PrivateMounts = lib.mkForce false; +} diff --git a/hosts/trantor/hardware-configuration.nix b/hosts/trantor/hardware-configuration.nix new file mode 100644 index 0000000..039129e --- /dev/null +++ b/hosts/trantor/hardware-configuration.nix @@ -0,0 +1,20 @@ +{ + lib, + modulesPath, + ... +}: + +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + + boot.initrd.availableKernelModules = [ + "xhci_pci" + "virtio_pci" + "virtio_scsi" + "usbhid" + ]; + + networking.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; +} diff --git a/hosts/trantor/networking.nix b/hosts/trantor/networking.nix new file mode 100644 index 0000000..4dcbe1e --- /dev/null +++ b/hosts/trantor/networking.nix @@ -0,0 +1,8 @@ +{ + networking = { + firewall = { + allowedTCPPorts = [ 25566 ]; + allowedUDPPorts = [ 25566 ]; + }; + }; +} diff --git a/hosts/trantor/nginx.nix b/hosts/trantor/nginx.nix new file mode 100644 index 0000000..56eed7c --- /dev/null +++ b/hosts/trantor/nginx.nix @@ -0,0 +1,61 @@ +{ + config, + lib, + inputs, + ... +}: + +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts services; + + # Get all unique domains from shared services on trantor (host = "trantor") + localDomains = lib.unique ( + map (s: s.domain) (lib.filter (s: s.host == "trantor") services) + ); + + # Generate ACME cert configs for all local domains + acmeCerts = lib.genAttrs localDomains (domain: { + group = "nginx"; + }); +in + +{ + security.acme = { + acceptTerms = true; + defaults = { + email = "baduhai@proton.me"; + dnsResolver = "1.1.1.1:53"; + dnsProvider = "cloudflare"; + credentialsFile = config.age.secrets.cloudflare.path; + }; + certs = acmeCerts; + }; + + services.nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + virtualHosts = { + "_" = { + default = true; + locations."/".return = "444"; + }; + }; + }; + + users.users.nginx.extraGroups = [ "acme" ]; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + age.secrets.cloudflare = { + file = ../../secrets/cloudflare.age; + owner = "nginx"; + group = "nginx"; + }; +} diff --git a/hosts/trantor/openssh.nix b/hosts/trantor/openssh.nix new file mode 100644 index 0000000..704b3df --- /dev/null +++ b/hosts/trantor/openssh.nix @@ -0,0 +1,23 @@ +{ ... }: + +{ + services = { + openssh = { + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + }; + }; + fail2ban.jails.sshd = { + settings = { + enabled = true; + port = "ssh"; + filter = "sshd"; + logpath = "/var/log/auth.log"; + maxretry = 3; + findtime = "10m"; + bantime = "1h"; + }; + }; + }; +} diff --git a/hosts/trantor/unbound.nix b/hosts/trantor/unbound.nix new file mode 100644 index 0000000..46808c6 --- /dev/null +++ b/hosts/trantor/unbound.nix @@ -0,0 +1,58 @@ +{ inputs, lib, ... }: + +let + utils = import ../../utils.nix { inherit inputs lib; }; +in + +{ + services.unbound = { + enable = true; + enableRootTrustAnchor = true; + settings = { + server = { + interface = [ + "0.0.0.0" + "::" + ]; + access-control = [ + "127.0.0.0/8 allow" + "100.64.0.0/10 allow" # Tailscale CGNAT range + "::1/128 allow" + "fd7a:115c:a1e0::/48 allow" # Tailscale IPv6 + ]; + + num-threads = 2; + msg-cache-size = "50m"; + rrset-cache-size = "100m"; + cache-min-ttl = 300; + cache-max-ttl = 86400; + prefetch = true; + prefetch-key = true; + hide-identity = true; + hide-version = true; + so-rcvbuf = "1m"; + so-sndbuf = "1m"; + + # Tailnet DNS records from shared services + local-zone = ''"baduhai.dev." transparent''; + local-data = map (e: ''"${e.domain}. IN A ${e.tailscaleIP}"'') utils.services; + }; + + forward-zone = [ + { + name = "."; + forward-addr = [ + "1.1.1.1@853#cloudflare-dns.com" + "1.0.0.1@853#cloudflare-dns.com" + ]; + forward-tls-upstream = true; + } + ]; + }; + }; + + networking.firewall = { + allowedTCPPorts = [ 53 ]; + allowedUDPPorts = [ 53 ]; + }; +} diff --git a/modules/ephemeral.nix b/modules/ephemeral.nix new file mode 100644 index 0000000..7403aac --- /dev/null +++ b/modules/ephemeral.nix @@ -0,0 +1,84 @@ +{ lib, config, ... }: + +let + cfg = config.ephemeral; +in +{ + options.ephemeral = { + enable = lib.mkEnableOption "ephemeral root with automatic rollback"; + + rootDevice = lib.mkOption { + type = lib.types.str; + example = "/dev/mapper/cryptroot"; + description = "Device path for the root btrfs filesystem"; + }; + + rootSubvolume = lib.mkOption { + type = lib.types.str; + example = "@root"; + description = "Name of the root btrfs subvolume"; + }; + + oldRootRetentionDays = lib.mkOption { + type = lib.types.int; + default = 30; + description = "Number of days to keep old root snapshots before deletion"; + }; + }; + + config = lib.mkIf cfg.enable { + boot.initrd.systemd.services.recreate-root = { + description = "Rolling over and creating new filesystem root"; + requires = [ "initrd-root-device.target" ]; + after = [ + "local-fs-pre.target" + "initrd-root-device.target" + ]; + requiredBy = [ "initrd-root-fs.target" ]; + before = [ "sysroot.mount" ]; + unitConfig = { + AssertPathExists = "/etc/initrd-release"; + DefaultDependencies = false; + }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + set -euo pipefail + + mkdir /btrfs_tmp + if ! mount ${cfg.rootDevice} /btrfs_tmp; then + echo "ERROR: Failed to mount ${cfg.rootDevice}" + exit 1 + fi + + if [[ -e /btrfs_tmp/${cfg.rootSubvolume} ]]; then + mkdir -p /btrfs_tmp/old_roots + timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/${cfg.rootSubvolume})" "+%Y-%m-%-d_%H:%M:%S") + mv /btrfs_tmp/${cfg.rootSubvolume} "/btrfs_tmp/old_roots/$timestamp" + fi + + delete_subvolume_recursively() { + IFS=$'\n' + for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do + delete_subvolume_recursively "/btrfs_tmp/$i" + done + btrfs subvolume delete "$1" + } + + for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +${toString cfg.oldRootRetentionDays}); do + delete_subvolume_recursively "$i" + done + + if ! btrfs subvolume create /btrfs_tmp/${cfg.rootSubvolume}; then + echo "ERROR: Failed to create subvolume ${cfg.rootSubvolume}" + umount /btrfs_tmp + exit 1 + fi + + umount /btrfs_tmp + ''; + }; + }; +} diff --git a/modules/qbittorrent.nix b/modules/qbittorrent.nix deleted file mode 100644 index 09123a5..0000000 --- a/modules/qbittorrent.nix +++ /dev/null @@ -1,123 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -with lib; -let - cfg = config.services.qbittorrent; - configDir = "${cfg.dataDir}/.config"; - openFilesLimit = 4096; -in -{ - options.services.qbittorrent = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Run qBittorrent headlessly as systemwide daemon - ''; - }; - - dataDir = mkOption { - type = types.path; - default = "/var/lib/qbittorrent"; - description = '' - The directory where qBittorrent will create files. - ''; - }; - - user = mkOption { - type = types.str; - default = "qbittorrent"; - description = '' - User account under which qBittorrent runs. - ''; - }; - - group = mkOption { - type = types.str; - default = "qbittorrent"; - description = '' - Group under which qBittorrent runs. - ''; - }; - - port = mkOption { - type = types.port; - default = 8080; - description = '' - qBittorrent web UI port. - ''; - }; - - openFirewall = mkOption { - type = types.bool; - default = false; - description = '' - Open services.qBittorrent.port to the outside network. - ''; - }; - - openFilesLimit = mkOption { - default = openFilesLimit; - description = '' - Number of files to allow qBittorrent to open. - ''; - }; - }; - - config = mkIf cfg.enable { - - environment.systemPackages = [ pkgs.qbittorrent ]; - - nixpkgs.overlays = [ - (final: prev: { - qbittorrent = prev.qbittorrent.override { guiSupport = false; }; - }) - ]; - - networking.firewall = mkIf cfg.openFirewall { - allowedTCPPorts = [ cfg.port ]; - allowedUDPPorts = [ cfg.port ]; - }; - - systemd.services.qbittorrent = { - after = [ "network.target" ]; - description = "qBittorrent Daemon"; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.qbittorrent ]; - serviceConfig = { - ExecStart = '' - ${pkgs.qbittorrent}/bin/qbittorrent-nox \ - --profile=${configDir} \ - --webui-port=${toString cfg.port} - ''; - # To prevent "Quit & shutdown daemon" from working; we want systemd to - # manage it! - Restart = "on-success"; - User = cfg.user; - Group = cfg.group; - UMask = "0002"; - LimitNOFILE = cfg.openFilesLimit; - }; - }; - - users.users = mkIf (cfg.user == "qbittorrent") { - qbittorrent = { - group = cfg.group; - home = cfg.dataDir; - createHome = true; - description = "qBittorrent Daemon user"; - }; - }; - - users.groups = mkIf (cfg.group == "qbittorrent") { - qbittorrent = { - gid = null; - }; - }; - }; -} diff --git a/nixosConfigurations.nix b/nixosConfigurations.nix new file mode 100644 index 0000000..c4969c1 --- /dev/null +++ b/nixosConfigurations.nix @@ -0,0 +1,55 @@ +{ inputs, ... }: +let + lib = inputs.nixpkgs.lib; + utils = import ./utils.nix { inherit inputs lib; }; + inherit (utils) mkHost; +in +{ + flake.nixosConfigurations = { + rotterdam = mkHost { + hostname = "rotterdam"; + tags = [ + "desktop" + "ai" + "bluetooth" + "dev" + "ephemeral" + "fwupd" + "gaming" + "libvirtd" + "networkmanager" + "podman" + ]; + }; + + io = mkHost { + hostname = "io"; + tags = [ + "desktop" + "ai" + "bluetooth" + "dev" + "ephemeral" + "networkmanager" + "podman" + ]; + }; + + alexandria = mkHost { + hostname = "alexandria"; + tags = [ + # "server" TODO: uncomment when 25.11 is out. + "fwupd" + ]; + }; + + trantor = mkHost { + hostname = "trantor"; + system = "aarch64-linux"; + tags = [ + "server" + "ephemeral" + ]; + }; + }; +} diff --git a/nixosModules.nix b/nixosModules.nix new file mode 100644 index 0000000..5fd416b --- /dev/null +++ b/nixosModules.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + flake.nixosModules = { + ephemeral = import ./modules/ephemeral.nix; + }; +} diff --git a/overlays.nix b/overlays.nix new file mode 100644 index 0000000..eab4edf --- /dev/null +++ b/overlays.nix @@ -0,0 +1,13 @@ +{ inputs, ... }: + +{ + flake.overlays = { + default = final: prev: { + base16-schemes = inputs.self.packages.${final.system}.base16-schemes; + fastfetch = inputs.self.packages.${final.system}.fastfetch; + hm-cli = inputs.self.packages.${final.system}.hm-cli; + kwrite = inputs.self.packages.${final.system}.kwrite; + toggleaudiosink = inputs.self.packages.${final.system}.toggleaudiosink; + }; + }; +} diff --git a/packages.nix b/packages.nix new file mode 100644 index 0000000..46979f8 --- /dev/null +++ b/packages.nix @@ -0,0 +1,15 @@ +{ ... }: + +{ + perSystem = + { pkgs, system, ... }: + { + packages = { + base16-schemes = pkgs.callPackage ./packages/base16-schemes.nix { }; + fastfetch = pkgs.callPackage ./packages/fastfetch.nix { }; + hm-cli = pkgs.callPackage ./packages/hm-cli.nix { }; + kwrite = pkgs.callPackage ./packages/kwrite.nix { }; + toggleaudiosink = pkgs.callPackage ./packages/toggleaudiosink.nix { }; + }; + }; +} diff --git a/packages/base16-schemes.nix b/packages/base16-schemes.nix new file mode 100644 index 0000000..ffd6c04 --- /dev/null +++ b/packages/base16-schemes.nix @@ -0,0 +1,32 @@ +{ + lib, + stdenv, + fetchFromGitHub, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "base16-schemes"; + version = "0-unstable-2025-06-04"; + + src = fetchFromGitHub { + owner = "tinted-theming"; + repo = "schemes"; + rev = "317a5e10c35825a6c905d912e480dfe8e71c7559"; + hash = "sha256-d4km8W7w2zCUEmPAPUoLk1NlYrGODuVa3P7St+UrqkM="; + }; + + installPhase = '' + runHook preInstall + + mkdir -p $out/share/themes/ + install base16/*.yaml $out/share/themes/ + + runHook postInstall + ''; + + meta = { + description = "All the color schemes for use in base16 packages"; + homepage = "https://github.com/tinted-theming/schemes"; + maintainers = [ lib.maintainers.DamienCassou ]; + license = lib.licenses.mit; + }; +}) diff --git a/packages/fastfetch.nix b/packages/fastfetch.nix new file mode 100644 index 0000000..fa8e0ea --- /dev/null +++ b/packages/fastfetch.nix @@ -0,0 +1,81 @@ +{ + lib, + pkgs ? import { }, +}: + +let + fastfetch-logo = pkgs.fetchurl { + url = "https://discourse.nixos.org/uploads/default/original/3X/3/6/36954e6d6aa32c8b00f50ca43f142d898c1ff535.png"; + hash = "sha256-aLHz8jSAFocrn+Pb4vRq0wtkYFJpBpZRevd+VoZC/PQ="; + }; + + fastfetch-config = pkgs.writeText "fastfetch-config.json" ( + builtins.toJSON { + "$schema" = "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json"; + modules = [ + "title" + "separator" + { + type = "os"; + keyWidth = 9; + } + { + type = "kernel"; + keyWidth = 9; + } + { + type = "uptime"; + keyWidth = 9; + } + { + type = "shell"; + keyWidth = 9; + } + "break" + { + type = "cpu"; + keyWidth = 11; + } + { + type = "memory"; + keyWidth = 11; + } + { + type = "swap"; + keyWidth = 11; + } + { + type = "disk"; + folders = "/"; + keyWidth = 11; + } + { + type = "command"; + key = "Systemd"; + keyWidth = 11; + text = "echo \"$(systemctl list-units --state=failed --no-legend | wc -l) failed units, $(systemctl list-jobs --no-legend | wc -l) queued jobs\""; + } + "break" + { + type = "command"; + key = "Public IP"; + keyWidth = 15; + text = "curl -s -4 ifconfig.me 2>/dev/null || echo 'N/A'"; + } + { + type = "command"; + key = "Tailscale IP"; + keyWidth = 15; + text = "tailscale ip -4 2>/dev/null || echo 'N/A'"; + } + { + type = "command"; + key = "Local IP"; + keyWidth = 15; + text = "ip -4 addr show scope global | grep inet | head -n1 | awk '{print $2}' | cut -d/ -f1"; + } + ]; + } + ); +in +pkgs.writeShellScriptBin "fastfetch" ''exec ${lib.getExe pkgs.fastfetch} --config ${fastfetch-config} --logo-type kitty --logo ${fastfetch-logo} --logo-padding-right 1 --logo-width 36 "$@" '' diff --git a/packages/hm-cli.nix b/packages/hm-cli.nix new file mode 100644 index 0000000..f6034ea --- /dev/null +++ b/packages/hm-cli.nix @@ -0,0 +1,105 @@ +{ + pkgs ? import { }, +}: + +pkgs.writeShellScriptBin "hm" '' + set -e + + HM="${pkgs.lib.getExe pkgs.home-manager}" + FLAKE_PATH="''${HM_PATH:-$HOME/.config/home-manager}" + FLAKE_OUTPUT="''${HM_USER:-$(whoami)@$(hostname)}" + + show_usage() { + cat < [args] + + Commands: + apply Switch to a new generation + generation list List all generations + generation delete ID... Delete specified generation(s) + generation rollback Rollback to the previous generation + generation switch ID Switch to the specified generation + generation cleanup Delete all but the current generation + + Environment Variables: + HM_PATH Override default flake path (~/.config/home-manager) + Currently set to "''${HM_PATH:-}" + HM_USER Override default user output ("$(whoami)@$(hostname)") + Currently set to "''${HM_USER:-}" + EOF + } + + if [[ $# -eq 0 ]]; then + show_usage + exit 1 + fi + + case "$1" in + apply) + "$HM" switch --flake "$FLAKE_PATH#$FLAKE_OUTPUT" -b bkp + ;; + generation) + if [[ $# -lt 2 ]]; then + echo "Error: generation command requires a subcommand" + show_usage + exit 1 + fi + + case "$2" in + list) + "$HM" generations + ;; + delete) + if [[ $# -lt 3 ]]; then + echo "Error: delete requires at least one generation ID" + exit 1 + fi + shift 2 + "$HM" remove-generations "$@" + ;; + rollback) + PREV_GEN=$("$HM" generations | \ + sed -n 's/^[[:space:]]*id \([0-9]\+\).*/\1/p' | \ + head -n 2 | tail -n 1) + if [[ -z "$PREV_GEN" ]]; then + echo "Error: could not determine previous generation (possibly only one generation exists)" + exit 1 + fi + "$HM" switch --flake "$FLAKE_PATH" --switch-generation "$PREV_GEN" -b bkp + ;; + switch) + if [[ $# -ne 3 ]]; then + echo "Error: switch requires exactly one generation ID" + exit 1 + fi + "$HM" switch --flake "$FLAKE_PATH" --switch-generation "$3" -b bkp + ;; + cleanup) + CURRENT_GEN=$("$HM" generations | sed -n 's/^.*id \([0-9]\+\) .* (current)$/\1/p') + if [[ -z "$CURRENT_GEN" ]]; then + echo "Error: could not determine current generation" + exit 1 + fi + OLD_GENS=$("$HM" generations | sed -n 's/^.*id \([0-9]\+\) .*/\1/p' | grep -v "^$CURRENT_GEN$") + if [[ -z "$OLD_GENS" ]]; then + echo "No old generations to delete" + else + echo "Deleting generations: $(echo $OLD_GENS | tr '\n' ' ')" + echo "$OLD_GENS" | xargs "$HM" remove-generations + echo "Cleanup complete. Current generation $CURRENT_GEN preserved." + fi + ;; + *) + echo "Error: unknown generation subcommand '$2'" + show_usage + exit 1 + ;; + esac + ;; + *) + echo "Error: unknown command '$1'" + show_usage + exit 1 + ;; + esac +'' diff --git a/packages/kwrite.nix b/packages/kwrite.nix new file mode 100644 index 0000000..14ebce1 --- /dev/null +++ b/packages/kwrite.nix @@ -0,0 +1,15 @@ +{ pkgs }: + +pkgs.symlinkJoin { + name = "kwrite"; + paths = [ pkgs.kdePackages.kate ]; + postBuild = '' + rm -rf $out/bin/kate \ + $out/bin/.kate-wrapped \ + $out/share/applications/org.kde.kate.desktop \ + $out/share/man \ + $out/share/icons/hicolor/*/apps/kate.png \ + $out/share/icons/hicolor/scalable/apps/kate.svg \ + $out/share/appdata/org.kde.kate.appdata.xml + ''; +} diff --git a/packages/plasticity.nix b/packages/plasticity.nix deleted file mode 100644 index 5ffbaeb..0000000 --- a/packages/plasticity.nix +++ /dev/null @@ -1,133 +0,0 @@ -{ - alsa-lib, - at-spi2-atk, - autoPatchelfHook, - cairo, - cups, - dbus, - desktop-file-utils, - expat, - fetchurl, - gdk-pixbuf, - gtk3, - gvfs, - hicolor-icon-theme, - lib, - libdrm, - libglvnd, - libnotify, - libsForQt5, - libxkbcommon, - mesa, - nspr, - nss, - openssl, - pango, - rpmextract, - stdenv, - systemd, - trash-cli, - vulkan-loader, - wrapGAppsHook3, - xdg-utils, - xorg, -}: -stdenv.mkDerivation rec { - pname = "plasticity"; - version = "24.2.3"; - - src = fetchurl { - url = "https://github.com/nkallen/plasticity/releases/download/v${version}/Plasticity-${version}-1.x86_64.rpm"; - hash = "sha256-iiVh4k5r5PXN1/VJZcropTMu36N2B/ECq2L5e59QxJY="; - }; - - passthru.updateScript = ./update.sh; - - nativeBuildInputs = [ - wrapGAppsHook3 - autoPatchelfHook - rpmextract - mesa - ]; - - buildInputs = [ - alsa-lib - at-spi2-atk - cairo - cups - dbus - desktop-file-utils - expat - gdk-pixbuf - gtk3 - gvfs - hicolor-icon-theme - libdrm - libnotify - libsForQt5.kde-cli-tools - libxkbcommon - nspr - nss - openssl - pango - stdenv.cc.cc.lib - trash-cli - xdg-utils - ]; - - runtimeDependencies = [ - systemd - libglvnd - vulkan-loader # may help with nvidia users - xorg.libX11 - xorg.libxcb - xorg.libXcomposite - xorg.libXdamage - xorg.libXext - xorg.libXfixes - xorg.libXrandr - xorg.libXtst - ]; - - dontUnpack = true; - - # can't find anything on the internet about these files, no clue what they do - autoPatchelfIgnoreMissingDeps = [ - "ACCAMERA.tx" - "AcMPolygonObj15.tx" - "ATEXT.tx" - "ISM.tx" - "RText.tx" - "SCENEOE.tx" - "TD_DbEntities.tx" - "TD_DbIO.tx" - "WipeOut.tx" - ]; - - installPhase = '' - runHook preInstall - - mkdir $out - cd $out - rpmextract $src - mv $out/usr/* $out - rm -r $out/usr - - runHook postInstall - ''; - - #--use-gl=egl for it to use hardware rendering it seems. Otherwise there are terrible framerates - postInstall = '' - substituteInPlace share/applications/Plasticity.desktop \ - --replace-fail 'Exec=Plasticity %U' "Exec=Plasticity --use-gl=egl %U" - ''; - - meta = with lib; { - description = "CAD for artists"; - homepage = "https://www.plasticity.xyz"; - mainProgram = "Plasticity"; - sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; - maintainers = with maintainers; [ imadnyc ]; - platforms = [ "x86_64-linux" ]; - }; -} diff --git a/packages/toggleaudiosink.nix b/packages/toggleaudiosink.nix new file mode 100644 index 0000000..623346f --- /dev/null +++ b/packages/toggleaudiosink.nix @@ -0,0 +1,48 @@ +{ + pkgs ? import { }, +}: + +pkgs.writeShellScriptBin "toggleaudiosink" '' + #!/usr/bin/env bash + + sound_server="pipewire" + + # Grab a count of how many audio sinks we have + sink_count=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -c "Sink #[[:digit:]]") + # Create an array of the actual sink IDs + sinks=() + mapfile -t sinks < <(${pkgs.pulseaudio}/bin/pactl list sinks | grep 'Sink #[[:digit:]]' | sed -n -e 's/.*Sink #\([[:digit:]]\)/\1/p') + # Get the ID of the active sink + active_sink_name=$(${pkgs.pulseaudio}/bin/pactl info | grep 'Default Sink:' | sed -n -e 's/.*Default Sink:[[:space:]]\+\(.*\)/\1/p') + active_sink=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -B 2 "$active_sink_name" | sed -n -e 's/Sink #\([[:digit:]]\)/\1/p' | head -n 1) + + # Get the ID of the last sink in the array + final_sink=''${sinks[$((sink_count - 1))]} + + # Find the index of the active sink + for index in "''${!sinks[@]}"; do + if [[ "''${sinks[$index]}" == "$active_sink" ]]; then + active_sink_index=$index + fi + done + + # Default to the first sink in the list + next_sink=''${sinks[0]} + next_sink_index=0 + + # If we're not at the end of the list, move up the list + if [[ $active_sink -ne $final_sink ]]; then + next_sink_index=$((active_sink_index + 1)) + next_sink=''${sinks[$next_sink_index]} + fi + + # Change the default sink + # Get the name of the next sink + next_sink_name=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -C 2 "Sink #$next_sink" | sed -n -e 's/.*Name:[[:space:]]\+\(.*\)/\1/p' | head -n 1) + ${pkgs.pulseaudio}/bin/pactl set-default-sink "$next_sink_name" + + # Move all inputs to the new sink + for app in $(${pkgs.pulseaudio}/bin/pactl list sink-inputs | sed -n -e 's/.*Sink Input #\([[:digit:]]\)/\1/p'); do + ${pkgs.pulseaudio}/bin/pactl "move-sink-input $app $next_sink" + done +'' diff --git a/readme.md b/readme.md index f19ab12..a2b815f 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,87 @@ -All my personal Nix and NixOS hosts, in a flake. +# Nix Configuration -|Host|Description|Nixpkgs version| -|:---|:---:|---:| -|alexandria|Personal server/NAS|24.05| -|io|Mobile workstation|unstable| -|rotterdam|Workstation|unstable| +My personal Nix configuration for multiple NixOS hosts, home-manager users, miscellaneous resources... too many things to list. If I could put my life in a flake I would. + +## Hosts + +### Desktop Systems +- **rotterdam** - Main desktop workstation (x86_64) + - Features: Desktop, AI tools, Bluetooth, Dev environment, Gaming, Virtualization (libvirtd), Podman + - Storage: Ephemeral root with LUKS encryption + +- **io** - Laptop workstation (x86_64) + - Features: Desktop, AI tools, Bluetooth, Dev environment, Podman + - Storage: Ephemeral root with LUKS encryption + +### Servers +- **alexandria** - Home server (x86_64) + - Hosts: Nextcloud, Vaultwarden, Jellyfin, Kanidm + +- **trantor** - Cloud server (aarch64) + - Hosts: Forgejo + - Cloud provider: Oracle Cloud Infrastructure + - Storage: Ephemeral root with btrfs + +## Home Manager Configurations + +- **user@rotterdam** - Full desktop setup with gaming, OBS, and complete development environment +- **user@io** - Lightweight desktop setup + +Both configurations include: +- btop, direnv, helix, starship, tmux +- Stylix theme management +- Fish shell with custom configurations + +## Terranix Configurations + +Infrastructure as code using Terranix (NixOS + Terraform/OpenTofu): + +- **oci-trantor** - Oracle Cloud Infrastructure provisioning for Trantor server +- **cloudflare-baduhaidev** - DNS and CDN configuration for baduhai.dev domain +- **tailscale-tailnet** - Tailscale network ACL and device management + +## Services + +All services are accessible via custom domains under baduhai.dev: + +- **Kanidm** (auth.baduhai.dev) - Identity and access management +- **Vaultwarden** (pass.baduhai.dev) - Password manager +- **Forgejo** (git.baduhai.dev) - Git forge (publicly accessible) +- **Nextcloud** (cloud.baduhai.dev) - File sync and collaboration +- **Jellyfin** (jellyfin.baduhai.dev) - Media server + +Services are accessible via: +- LAN for alexandria-hosted services +- Tailscale VPN for all services +- Public internet for Forgejo only + +## Notable Features + +### Ephemeral Root +Rotterdam, io, and trantor use an ephemeral root filesystem that resets on every boot: +- Root filesystem is automatically rolled back using btrfs snapshots +- Old snapshots retained for 30 days +- Persistent data stored in dedicated subvolumes +- Implements truly stateless systems + +### Custom DNS Architecture +- Unbound DNS servers on both alexandria and trantor +- Service routing based on visibility flags (public/LAN/Tailscale) +- Split-horizon DNS for optimal access paths + +### Security +- LUKS full-disk encryption on desktop systems +- Fail2ban on public-facing servers +- agenix for secrets management +- Tailscale for secure remote access + +### Desktop Environment +- Custom Niri window manager (Wayland compositor) +- Using forked version with auto-centering feature +- Stylix for consistent theming + +### Development Setup +- Nix flakes for reproducible builds +- deploy-rs for automated deployments +- Podman for containerization +- Complete AI tooling integration diff --git a/secrets/cloudflare.age b/secrets/cloudflare.age index a2ea31f..028e964 100644 Binary files a/secrets/cloudflare.age and b/secrets/cloudflare.age differ diff --git a/secrets/forgejo-root-password.age b/secrets/forgejo-root-password.age new file mode 100644 index 0000000..90be612 Binary files /dev/null and b/secrets/forgejo-root-password.age differ diff --git a/secrets/nextcloud-adminpass.age b/secrets/nextcloud-adminpass.age index 4adb2b1..b4a29fa 100644 Binary files a/secrets/nextcloud-adminpass.age and b/secrets/nextcloud-adminpass.age differ diff --git a/secrets/nextcloud-secrets.json.age b/secrets/nextcloud-secrets.json.age index 3860d4e..02d170d 100644 Binary files a/secrets/nextcloud-secrets.json.age and b/secrets/nextcloud-secrets.json.age differ diff --git a/secrets/paperless.age b/secrets/paperless.age deleted file mode 100644 index 01199b7..0000000 --- a/secrets/paperless.age +++ /dev/null @@ -1,13 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 hi+lKA 3Oayrcg8bbzLNyuFqv8J0W9IJXL9SttFfU9yyysoD2Y -Uoxk9Ns1TwreeCyJ/7Euyqn57DY1spd6j3oZDqL65X0 --> ssh-ed25519 SP9f6A FInq9erSMD008Le4Va/28fAPXnTLSWioYWsTBlkJg2k -SG9fEh+eLnUHcC36PHZbkD+pQVRX4RLJj1vxMeSKdNk --> ssh-ed25519 8YSAiw hOqCc9a6K7RAwD1CY7uQ4se4mynx0z4AmoNhxmWJtQg -j+MYuftCyA7RDlzUciTxFyd/Esqzxpcm+ccKu4NNrmU --> ssh-ed25519 3Chb7w oCX+CYB+fobvBy/5EcUJMxzwkwA+gQOY2tq17Ui68nw -B1feop9p1RDBXCyBCxIMZyd++QM2dnDrU12m6rwz5/4 --> ssh-ed25519 J6tVTA PXVULNtK26OEKApHzOM2o6odRQNa9KbzjmAh2xgkHk4 -GLSEROgoiNVIVUhSpZWlg6q62GJHXRNsi1t7OwRw5MM ---- ddMx67t9wQFDJUlwFCDPvsUAR/JRUNweS28Erojuw8A -5/d}+cZM{-jo(UY{oa|˨~4xPހ \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 6feadc4..a90cd74 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -1,28 +1,35 @@ let - io-user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcwF1yuWEfYGScNocEbs0AmGxyTIzGc4/IhpU587SJE"; - io-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKCIrKJk5zWzWEHvLMPMK8T3PyeBjsCsqzxPN+OrXfhA"; - io = [ - io-user - io-host - ]; + io-user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3Y0PVpGfJHonqDS7qoCFhqzUvqGq9I9sax+F9e/5cs user@io"; + io = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKCIrKJk5zWzWEHvLMPMK8T3PyeBjsCsqzxPN+OrXfhA root@io"; - rotterdam-user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL"; - rotterdam-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK7zAxgU8LNi5/O5XgoOcLKjbNMmO2S7jAuCI9Nr/V4v"; - rotterdam = [ - rotterdam-user - rotterdam-host - ]; + rotterdam-user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL user@rotterdam"; + rotterdam = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIjXcqQqlu03x2VVTdWOyxtKRszXAKX0AxTkGvF1oeJL root@rotterdam"; - alexandria-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK95QueW+jp1ZmF299Xr3XkgHJ6dL7aZVsfWxqbOKVKA"; - alexandria = [ alexandria-host ]; + alexandria = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK95QueW+jp1ZmF299Xr3XkgHJ6dL7aZVsfWxqbOKVKA root@alexandria"; - desktops = io ++ rotterdam; - servers = alexandria; - all-hosts = desktops ++ servers; + trantor = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIh/2u5pr/iPVeavlsor5hbTtsgUfP1JpzZVco2YQAo3 root@trantor"; in + { - "nextcloud-secrets.json.age".publicKeys = all-hosts; - "nextcloud-adminpass.age".publicKeys = all-hosts; - "cloudflare.age".publicKeys = all-hosts; - "paperless.age".publicKeys = all-hosts; + "cloudflare.age".publicKeys = [ + io-user + rotterdam-user + alexandria + trantor + ]; + "nextcloud-adminpass.age".publicKeys = [ + io-user + rotterdam-user + alexandria + ]; + "nextcloud-secrets.json.age".publicKeys = [ + io-user + rotterdam-user + alexandria + ]; + "forgejo-root-password.age".publicKeys = [ + io-user + rotterdam-user + trantor + ]; } diff --git a/shared/services.nix b/shared/services.nix new file mode 100644 index 0000000..44f9208 --- /dev/null +++ b/shared/services.nix @@ -0,0 +1,48 @@ +# Shared service definitions for cross-host configuration +# Used by: +# - alexandria: DNS server (LAN) + service hosting (vaultwarden, nextcloud, jellyfin, kanidm) +# - trantor: DNS server (Tailnet) + service hosting (forgejo) +{ + services = [ + { + name = "kanidm"; + domain = "auth.baduhai.dev"; + host = "alexandria"; + lanIP = "192.168.15.142"; + tailscaleIP = "100.76.19.50"; + port = 8443; + } + { + name = "vaultwarden"; + domain = "pass.baduhai.dev"; + host = "alexandria"; + lanIP = "192.168.15.142"; + tailscaleIP = "100.76.19.50"; + port = 8222; + } + { + name = "forgejo"; + domain = "git.baduhai.dev"; + host = "trantor"; + public = true; + tailscaleIP = "100.108.5.90"; + port = 3000; + } + { + name = "nextcloud"; + domain = "cloud.baduhai.dev"; + host = "alexandria"; + lanIP = "192.168.15.142"; + tailscaleIP = "100.76.19.50"; + port = 443; + } + { + name = "jellyfin"; + domain = "jellyfin.baduhai.dev"; + host = "alexandria"; + lanIP = "192.168.15.142"; + tailscaleIP = "100.76.19.50"; + port = 8096; + } + ]; +} diff --git a/terranix/cloudflare/baduhai.dev.nix b/terranix/cloudflare/baduhai.dev.nix new file mode 100644 index 0000000..1b456f3 --- /dev/null +++ b/terranix/cloudflare/baduhai.dev.nix @@ -0,0 +1,86 @@ +# Required environment variables: +# CLOUDFLARE_API_TOKEN - API token with "Edit zone DNS" permissions +# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage +# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage + +{ config, lib, ... }: + +let + inherit (import ../../shared/services.nix) services; + + # Helper to extract subdomain from full domain (e.g., "git.baduhai.dev" -> "git") + getSubdomain = domain: lib.head (lib.splitString "." domain); + + # Generate DNS records for services + # Public services point to trantor's public IP + # Private services point to their tailscale IP + mkServiceRecords = lib.listToAttrs ( + lib.imap0 ( + i: svc: + let + subdomain = getSubdomain svc.domain; + targetIP = + if svc.public or false then + config.data.terraform_remote_state.trantor "outputs.instance_public_ip" + else + svc.tailscaleIP; + in + { + name = "service_${toString i}"; + value = { + zone_id = config.variable.zone_id.default; + name = subdomain; + type = "A"; + content = targetIP; + proxied = false; + ttl = 3600; + }; + } + ) services + ); +in + +{ + terraform.required_providers.cloudflare = { + source = "cloudflare/cloudflare"; + version = "~> 5.0"; + }; + + terraform.backend.s3 = { + bucket = "terraform-state"; + key = "cloudflare/baduhai.dev.tfstate"; + region = "auto"; + endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com"; + skip_credentials_validation = true; + skip_metadata_api_check = true; + skip_region_validation = true; + skip_requesting_account_id = true; + use_path_style = true; + }; + + variable = { + zone_id = { + default = "c63a8332fdddc4a8e5612ddc54557044"; + type = "string"; + }; + }; + + data = { + terraform_remote_state.trantor = { + backend = "s3"; + config = { + bucket = "terraform-state"; + key = "oci/trantor.tfstate"; + region = "auto"; + endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com"; + skip_credentials_validation = true; + skip_metadata_api_check = true; + skip_region_validation = true; + skip_requesting_account_id = true; + use_path_style = true; + }; + }; + }; + + resource.cloudflare_dns_record = mkServiceRecords; +} diff --git a/terranix/cloudflare/kernelpanic.space.nix b/terranix/cloudflare/kernelpanic.space.nix new file mode 100644 index 0000000..e69de29 diff --git a/terranix/oci/terminus.nix b/terranix/oci/terminus.nix new file mode 100644 index 0000000..e69de29 diff --git a/terranix/oci/trantor.nix b/terranix/oci/trantor.nix new file mode 100644 index 0000000..170ad04 --- /dev/null +++ b/terranix/oci/trantor.nix @@ -0,0 +1,258 @@ +# Required environment variables: +# instead of OCI variables, ~/.oci/config may also be used +# OCI_TENANCY_OCID - Oracle tenancy OCID (or use TF_VAR_* to override variables) +# OCI_USER_OCID - Oracle user OCID +# OCI_FINGERPRINT - API key fingerprint +# OCI_PRIVATE_KEY_PATH - Path to OCI API private key +# AWS variables are required +# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage +# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage + +{ config, ... }: + +{ + terraform.required_providers.oci = { + source = "oracle/oci"; + version = "~> 7.0"; + }; + + provider.oci.region = "sa-saopaulo-1"; + + terraform.backend.s3 = { + bucket = "terraform-state"; + key = "oci/trantor.tfstate"; + region = "auto"; + endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com"; + skip_credentials_validation = true; + skip_metadata_api_check = true; + skip_region_validation = true; + skip_requesting_account_id = true; + use_path_style = true; + }; + + variable = { + tenancy_ocid = { + default = "ocid1.tenancy.oc1..aaaaaaaap3vfdz4piygqza6e6zqunbcuso43ddqfo3ydmpmnomidyghh7rvq"; + type = "string"; + }; + + compartment_name = { + default = "trantor"; + type = "string"; + }; + + vcn_cidr = { + default = "10.0.0.0/24"; + type = "string"; + }; + + instance_name = { + default = "trantor"; + type = "string"; + }; + + ssh_public_keys = { + default = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICQPkAyy+Du9Omc2WtnUF2TV8jFAF4H6mJi2D4IZ1nzg user@himalia" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3Y0PVpGfJHonqDS7qoCFhqzUvqGq9I9sax+F9e/5cs user@io" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL user@rotterdam" + ]; + type = "list(string)"; + }; + }; + + data = { + oci_identity_availability_domains.ads = { + compartment_id = config.variable.tenancy_ocid.default; + }; + + oci_core_images.ubuntu_arm = { + compartment_id = config.variable.tenancy_ocid.default; + operating_system = "Canonical Ubuntu"; + operating_system_version = "24.04"; + shape = "VM.Standard.A1.Flex"; + sort_by = "TIMECREATED"; + sort_order = "DESC"; + }; + }; + + resource = { + oci_identity_compartment.trantor = { + compartment_id = config.variable.tenancy_ocid.default; + description = "trantor infrastructure compartment"; + name = config.variable.compartment_name.default; + }; + + oci_core_vcn.vcn = { + compartment_id = config.resource.oci_identity_compartment.trantor "id"; + cidr_blocks = [ config.variable.vcn_cidr.default ]; + display_name = "trantor-vcn"; + dns_label = "trantor"; + }; + + oci_core_internet_gateway.ig = { + compartment_id = config.resource.oci_identity_compartment.trantor "id"; + vcn_id = config.resource.oci_core_vcn.vcn "id"; + display_name = "trantor-ig"; + enabled = true; + }; + + oci_core_route_table.rt = { + compartment_id = config.resource.oci_identity_compartment.trantor "id"; + vcn_id = config.resource.oci_core_vcn.vcn "id"; + display_name = "trantor-rt"; + + route_rules = [ + { + network_entity_id = config.resource.oci_core_internet_gateway.ig "id"; + destination = "0.0.0.0/0"; + destination_type = "CIDR_BLOCK"; + } + ]; + }; + + oci_core_security_list.sl = { + compartment_id = config.resource.oci_identity_compartment.trantor "id"; + vcn_id = config.resource.oci_core_vcn.vcn "id"; + display_name = "trantor-sl"; + + egress_security_rules = [ + { + destination = "0.0.0.0/0"; + protocol = "all"; + stateless = false; + } + ]; + + ingress_security_rules = [ + { + protocol = "6"; # TCP + source = "0.0.0.0/0"; + stateless = false; + tcp_options = { + min = 22; + max = 22; + }; + } + { + protocol = "6"; # TCP + source = "0.0.0.0/0"; + stateless = false; + tcp_options = { + min = 80; + max = 80; + }; + } + { + protocol = "6"; # TCP + source = "0.0.0.0/0"; + stateless = false; + tcp_options = { + min = 443; + max = 443; + }; + } + { + protocol = "6"; # TCP + source = "0.0.0.0/0"; + stateless = false; + tcp_options = { + min = 25565; + max = 25565; + }; + } + { + protocol = "6"; # TCP + source = "0.0.0.0/0"; + stateless = false; + tcp_options = { + min = 19132; + max = 19133; + }; + } + { + protocol = "17"; # UDP + source = "0.0.0.0/0"; + stateless = false; + udp_options = { + min = 19132; + max = 19133; + }; + } + ]; + }; + + oci_core_subnet.subnet = { + compartment_id = config.resource.oci_identity_compartment.trantor "id"; + vcn_id = config.resource.oci_core_vcn.vcn "id"; + cidr_block = config.variable.vcn_cidr.default; + display_name = "trantor-subnet"; + dns_label = "subnet"; + route_table_id = config.resource.oci_core_route_table.rt "id"; + security_list_ids = [ (config.resource.oci_core_security_list.sl "id") ]; + prohibit_public_ip_on_vnic = false; + }; + + oci_core_instance.trantor = { + availability_domain = config.data.oci_identity_availability_domains.ads "availability_domains[0].name"; + compartment_id = config.resource.oci_identity_compartment.trantor "id"; + display_name = config.variable.instance_name.default; + shape = "VM.Standard.A1.Flex"; + + shape_config = { + ocpus = 2; + memory_in_gbs = 12; + }; + + source_details = { + source_type = "image"; + source_id = config.data.oci_core_images.ubuntu_arm "images[0].id"; + boot_volume_size_in_gbs = 100; + }; + + create_vnic_details = { + subnet_id = config.resource.oci_core_subnet.subnet "id"; + display_name = "trantor-vnic"; + assign_public_ip = true; + hostname_label = config.variable.instance_name.default; + }; + + metadata = { + ssh_authorized_keys = builtins.concatStringsSep "\n" config.variable.ssh_public_keys.default; + }; + + preserve_boot_volume = false; + }; + + oci_budget_budget.trantor_budget = { + compartment_id = config.variable.tenancy_ocid.default; + targets = [ (config.resource.oci_identity_compartment.trantor "id") ]; + amount = 1; + reset_period = "MONTHLY"; + display_name = "trantor-budget"; + description = "Monthly budget for trantor compartment"; + target_type = "COMPARTMENT"; + }; + + oci_budget_alert_rule.daily_spend_alert = { + budget_id = config.resource.oci_budget_budget.trantor_budget "id"; + type = "ACTUAL"; + threshold = 5; + threshold_type = "PERCENTAGE"; + display_name = "daily-spend-alert"; + recipients = "baduhai@proton.me"; + description = "Alert when daily spending exceeds $0.05"; + message = "Daily spending has exceeded $0.05 in the trantor compartment"; + }; + }; + + output = { + compartment_id = { + value = config.resource.oci_identity_compartment.trantor "id"; + }; + + instance_public_ip = { + value = config.resource.oci_core_instance.trantor "public_ip"; + }; + }; +} diff --git a/terranix/tailscale/tailnet.nix b/terranix/tailscale/tailnet.nix new file mode 100644 index 0000000..929e79b --- /dev/null +++ b/terranix/tailscale/tailnet.nix @@ -0,0 +1,43 @@ +# Required environment variables: +# TAILSCALE_API_KEY - Tailscale API key with appropriate permissions +# TAILSCALE_TAILNET - Your tailnet name (e.g., "user@example.com" or "example.org.github") +# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage +# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage + +{ config, ... }: + +{ + terraform.required_providers.tailscale = { + source = "tailscale/tailscale"; + version = "~> 0.17"; + }; + + terraform.backend.s3 = { + bucket = "terraform-state"; + key = "tailscale/tailnet.tfstate"; + region = "auto"; + endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com"; + skip_credentials_validation = true; + skip_metadata_api_check = true; + skip_region_validation = true; + skip_requesting_account_id = true; + use_path_style = true; + }; + + variable = { + trantor_tailscale_ip = { + default = "100.108.5.90"; + type = "string"; + }; + }; + + resource = { + tailscale_dns_nameservers.global = { + nameservers = [ + config.variable.trantor_tailscale_ip.default + "1.1.1.1" + "1.0.0.1" + ]; + }; + }; +} diff --git a/terranixConfigurations.nix b/terranixConfigurations.nix new file mode 100644 index 0000000..12c90d1 --- /dev/null +++ b/terranixConfigurations.nix @@ -0,0 +1,27 @@ +{ inputs, ... }: + +{ + imports = [ + inputs.terranix.flakeModule + ]; + + perSystem = + { pkgs, ... }: + + { + terranix.terranixConfigurations = { + oci-trantor = { + modules = [ ./terranix/oci/trantor.nix ]; + terraformWrapper.package = pkgs.opentofu; + }; + cloudflare-baduhaidev = { + modules = [ ./terranix/cloudflare/baduhai.dev.nix ]; + terraformWrapper.package = pkgs.opentofu; + }; + tailscale-tailnet = { + modules = [ ./terranix/tailscale/tailnet.nix ]; + terraformWrapper.package = pkgs.opentofu; + }; + }; + }; +} diff --git a/users/common/default.nix b/users/common/default.nix deleted file mode 100644 index a6eeaf4..0000000 --- a/users/common/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: - -{ - imports = [ - ./home.nix - ./programs.nix - ]; -} diff --git a/users/common/home.nix b/users/common/home.nix deleted file mode 100644 index 5bafc2f..0000000 --- a/users/common/home.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ pkgs, ... }: - -{ - home = { - username = "user"; - homeDirectory = "/home/user"; - stateVersion = "22.05"; - sessionVariables = { - EDITOR = "hx"; - }; - packages = with pkgs; [ nix-your-shell ]; - }; -} diff --git a/users/common/programs.nix b/users/common/programs.nix deleted file mode 100644 index 1dc9390..0000000 --- a/users/common/programs.nix +++ /dev/null @@ -1,156 +0,0 @@ -{ pkgs, ... }: - -{ - programs = { - password-store.enable = true; - - bash = { - enable = true; - historyFile = "~/.cache/bash_history"; - }; - - helix = { - enable = true; - settings = { - editor = { - file-picker.hidden = false; - idle-timeout = 0; - line-number = "relative"; - cursor-shape = { - normal = "block"; - insert = "bar"; - select = "underline"; - }; - soft-wrap.enable = true; - auto-format = true; - indent-guides.render = true; - }; - keys.normal.space = { - space = "file_picker"; - w = ":w"; - q = ":q"; - esc = [ - "collapse_selection" - "keep_primary_selection" - ]; - }; - }; - languages = { - language = [ - { - name = "nix"; - auto-format = true; - formatter.command = "nixfmt"; - } - { - name = "typst"; - auto-format = true; - formatter.command = "typstyle -c 1000 -i"; - } - ]; - }; - }; - - direnv = { - enable = true; - nix-direnv.enable = true; - }; - - tmux = { - enable = true; - clock24 = true; - terminal = "xterm-256color"; - mouse = true; - keyMode = "vi"; - }; - - starship = { - enable = true; - enableBashIntegration = true; - enableFishIntegration = true; - settings = { - add_newline = false; - format = '' - $directory$git_branch$git_status$nix_shell - [ ❯ ](bold green) - ''; - right_format = "$cmd_duration$character"; - character = { - error_symbol = "[](red)"; - success_symbol = "[󱐋](green)"; - }; - cmd_duration = { - format = "[󰄉 $duration ]($style)"; - style = "yellow"; - min_time = 500; - }; - git_branch = { - symbol = " "; - style = "purple"; - }; - git_status.style = "red"; - nix_shell = { - format = "via [$symbol$state]($style)"; - heuristic = true; - style = "blue"; - symbol = "󱄅 "; - }; - }; - }; - - git = { - enable = true; - diff-so-fancy.enable = true; - userName = "William"; - userEmail = "baduhai@proton.me"; - }; - - btop = { - enable = true; - settings = { - theme_background = false; - proc_sorting = "cpu direct"; - update_ms = 500; - }; - }; - - fish = { - enable = true; - interactiveShellInit = "nix-your-shell fish | source"; - loginShellInit = "nix-your-shell fish | source"; - functions = { - fish_greeting = ""; - tsh = "ssh -o RequestTTY=yes $argv tmux -u -CC new -A -s tmux-main"; - }; - plugins = [ - { - name = "bang-bang"; - src = pkgs.fetchFromGitHub { - owner = "oh-my-fish"; - repo = "plugin-bang-bang"; - rev = "f969c618301163273d0a03d002614d9a81952c1e"; - sha256 = "sha256-A8ydBX4LORk+nutjHurqNNWFmW6LIiBPQcxS3x4nbeQ="; - }; - } - { - name = "z"; - src = pkgs.fetchFromGitHub { - owner = "jethrokuan"; - repo = "z"; - rev = "85f863f20f24faf675827fb00f3a4e15c7838d76"; - sha256 = "sha256-+FUBM7CodtZrYKqU542fQD+ZDGrd2438trKM0tIESs0="; - }; - } - { - name = "sponge"; - src = pkgs.fetchFromGitHub { - owner = "meaningful-ooo"; - repo = "sponge"; - rev = "384299545104d5256648cee9d8b117aaa9a6d7be"; - sha256 = "sha256-MdcZUDRtNJdiyo2l9o5ma7nAX84xEJbGFhAVhK+Zm1w="; - }; - } - ]; - }; - }; -} diff --git a/users/desktops/common/default.nix b/users/desktops/common/default.nix deleted file mode 100644 index 5ef9e0a..0000000 --- a/users/desktops/common/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ ... }: - -{ - imports = [ - ./programs.nix - ]; -} diff --git a/users/desktops/common/programs.nix b/users/desktops/common/programs.nix deleted file mode 100644 index f1e4665..0000000 --- a/users/desktops/common/programs.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ pkgs, ... }: - -{ - fonts.fontconfig.enable = true; - - programs = { - password-store.package = pkgs.pass-wayland; - - mangohud.enable = true; - - obs-studio = { - enable = true; - plugins = [ - pkgs.obs-studio-plugins.obs-vkcapture - pkgs.obs-studio-plugins.obs-backgroundremoval - pkgs.obs-studio-plugins.obs-pipewire-audio-capture - ]; - }; - - fish = { - functions = { - sysrebuild = "nh os switch --ask"; - sysrebuild-boot = "nh os boot --ask"; - sysupdate = "nix flake update --commit-lock-file --flake /home/user/Projects/personal/nix-config"; - }; - }; - }; -} diff --git a/users/desktops/user.nix b/users/desktops/user.nix deleted file mode 100644 index 80e1f3a..0000000 --- a/users/desktops/user.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ ... }: - -{ - imports = [ - # Host-common imports - ../common - # Desktop-common imports - ./common - ]; -} diff --git a/users/modules/btop.nix b/users/modules/btop.nix new file mode 100644 index 0000000..c19c4bb --- /dev/null +++ b/users/modules/btop.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: + +{ + programs.btop = { + enable = true; + settings = { + theme_background = false; + proc_sorting = "cpu direct"; + update_ms = 500; + }; + }; +} \ No newline at end of file diff --git a/users/modules/comma.nix b/users/modules/comma.nix new file mode 100644 index 0000000..0aad530 --- /dev/null +++ b/users/modules/comma.nix @@ -0,0 +1,7 @@ +{ inputs, ... }: + +{ + imports = [ inputs.nix-index-database.homeModules.nix-index ]; + + programs.nix-index-database.comma.enable = true; +} diff --git a/users/modules/common/bash.nix b/users/modules/common/bash.nix new file mode 100644 index 0000000..a5a0823 --- /dev/null +++ b/users/modules/common/bash.nix @@ -0,0 +1,8 @@ +{ pkgs, ... }: + +{ + programs.bash = { + enable = true; + historyFile = "~/.cache/bash_history"; + }; +} \ No newline at end of file diff --git a/users/modules/common/fish.nix b/users/modules/common/fish.nix new file mode 100644 index 0000000..c753297 --- /dev/null +++ b/users/modules/common/fish.nix @@ -0,0 +1,32 @@ +{ pkgs, lib, ... }: + +{ + programs.fish = { + enable = true; + interactiveShellInit = '' + set fish_greeting + ${lib.getExe pkgs.nix-your-shell} fish | source + ''; + loginShellInit = "${lib.getExe pkgs.nix-your-shell} fish | source"; + plugins = [ + { + name = "bang-bang"; + src = pkgs.fetchFromGitHub { + owner = "oh-my-fish"; + repo = "plugin-bang-bang"; + rev = "f969c618301163273d0a03d002614d9a81952c1e"; + sha256 = "sha256-A8ydBX4LORk+nutjHurqNNWFmW6LIiBPQcxS3x4nbeQ="; + }; + } + { + name = "z"; + src = pkgs.fetchFromGitHub { + owner = "jethrokuan"; + repo = "z"; + rev = "067e867debee59aee231e789fc4631f80fa5788e"; + sha256 = "sha256-emmjTsqt8bdI5qpx1bAzhVACkg0MNB/uffaRjjeuFxU="; + }; + } + ]; + }; +} diff --git a/users/modules/common/hm-cli.nix b/users/modules/common/hm-cli.nix new file mode 100644 index 0000000..d2ed715 --- /dev/null +++ b/users/modules/common/hm-cli.nix @@ -0,0 +1,10 @@ +{ pkgs, ... }: + +{ + home = { + packages = with pkgs; [ hm-cli ]; + sessionVariables = { + HM_PATH = "/etc/nixos"; + }; + }; +} diff --git a/users/modules/desktop/desktop.nix b/users/modules/desktop/desktop.nix new file mode 100644 index 0000000..6940e1f --- /dev/null +++ b/users/modules/desktop/desktop.nix @@ -0,0 +1,132 @@ +{ + inputs, + pkgs, + ... +}: + +{ + imports = [ inputs.vicinae.homeManagerModules.default ]; + + fonts.fontconfig.enable = true; + + home.packages = with pkgs; [ xwayland-satellite ]; + + services.vicinae = { + enable = true; + autoStart = true; + }; + + programs = { + + ghostty = { + enable = true; + settings = { + cursor-style = "block"; + shell-integration-features = "no-cursor"; + cursor-style-blink = false; + custom-shader = "${builtins.fetchurl { + url = "https://raw.githubusercontent.com/hackr-sh/ghostty-shaders/cb6eb4b0d1a3101c869c62e458b25a826f9dcde3/cursor_blaze.glsl"; + sha256 = "sha256:0g2lgqjdrn3c51glry7x2z30y7ml0y61arl5ykmf4yj0p85s5f41"; + }}"; + bell-features = ""; + gtk-titlebar-style = "tabs"; + keybind = [ "shift+enter=text:\\x1b\\r" ]; + }; + }; + + password-store = { + enable = true; + package = pkgs.pass-wayland; + }; + }; + + xdg = { + enable = true; + userDirs.enable = true; + mimeApps = { + enable = true; + defaultApplications = { + "text/html" = [ + "re.sonny.Junction.desktop" + "zen-browser.desktop" + "torbrowser.desktop" + ]; + "x-scheme-handler/http" = [ + "re.sonny.Junction.desktop" + "zen-browser.desktop" + "torbrowser.desktop" + ]; + "x-scheme-handler/https" = [ + "re.sonny.Junction.desktop" + "zen-browser.desktop" + "torbrowser.desktop" + ]; + "x-scheme-handler/about" = [ + "re.sonny.Junction.desktop" + "zen-browser.desktop" + "torbrowser.desktop" + ]; + "x-scheme-handler/unknown" = [ + "re.sonny.Junction.desktop" + "zen-browser.desktop" + "torbrowser.desktop" + ]; + "image/jpeg" = "org.gnome.Loupe.desktop"; + "image/png" = "org.gnome.Loupe.desktop"; + "image/gif" = "org.gnome.Loupe.desktop"; + "image/webp" = "org.gnome.Loupe.desktop"; + "image/bmp" = "org.gnome.Loupe.desktop"; + "image/svg+xml" = "org.gnome.Loupe.desktop"; + "image/tiff" = "org.gnome.Loupe.desktop"; + "video/mp4" = "io.bassi.Showtime.desktop"; + "video/x-matroska" = "io.bassi.Showtime.desktop"; + "video/webm" = "io.bassi.Showtime.desktop"; + "video/mpeg" = "io.bassi.Showtime.desktop"; + "video/x-msvideo" = "io.bassi.Showtime.desktop"; + "video/quicktime" = "io.bassi.Showtime.desktop"; + "video/x-flv" = "io.bassi.Showtime.desktop"; + "audio/mpeg" = "io.bassi.Showtime.desktop"; + "audio/flac" = "io.bassi.Showtime.desktop"; + "audio/ogg" = "io.bassi.Showtime.desktop"; + "audio/wav" = "io.bassi.Showtime.desktop"; + "audio/mp4" = "io.bassi.Showtime.desktop"; + "audio/x-opus+ogg" = "io.bassi.Showtime.desktop"; + "application/pdf" = [ + "org.gnome.Papers.desktop" + "zen-browser.desktop" + ]; + "text/plain" = "Helix.desktop"; + "text/markdown" = "Helix.desktop"; + "text/x-log" = "Helix.desktop"; + "application/x-shellscript" = "Helix.desktop"; + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" = + "onlyoffice-desktopeditors.desktop"; # DOCX + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" = + "onlyoffice-desktopeditors.desktop"; # XLSX + "application/vnd.openxmlformats-officedocument.presentationml.presentation" = + "onlyoffice-desktopeditors.desktop"; # PPTX + "application/vnd.oasis.opendocument.text" = "onlyoffice-desktopeditors.desktop"; # ODT + "application/vnd.oasis.opendocument.spreadsheet" = "onlyoffice-desktopeditors.desktop"; # ODS + "application/vnd.oasis.opendocument.presentation" = "onlyoffice-desktopeditors.desktop"; # ODP + "application/msword" = "onlyoffice-desktopeditors.desktop"; # DOC + "application/vnd.ms-excel" = "onlyoffice-desktopeditors.desktop"; # XLS + "application/vnd.ms-powerpoint" = "onlyoffice-desktopeditors.desktop"; # PPT + "application/zip" = "org.gnome.FileRoller.desktop"; + "application/x-tar" = "org.gnome.FileRoller.desktop"; + "application/x-compressed-tar" = "org.gnome.FileRoller.desktop"; + "application/x-bzip-compressed-tar" = "org.gnome.FileRoller.desktop"; + "application/x-xz-compressed-tar" = "org.gnome.FileRoller.desktop"; + "application/x-7z-compressed" = "org.gnome.FileRoller.desktop"; + "application/x-rar" = "org.gnome.FileRoller.desktop"; + "application/gzip" = "org.gnome.FileRoller.desktop"; + "application/x-bzip" = "org.gnome.FileRoller.desktop"; + "inode/directory" = "org.gnome.Nautilus.desktop"; + }; + }; + }; + + # Set Ghostty as default terminal + home.sessionVariables = { + TERMINAL = "ghostty"; + }; +} diff --git a/users/modules/desktop/niri.nix b/users/modules/desktop/niri.nix new file mode 100644 index 0000000..0cb5db8 --- /dev/null +++ b/users/modules/desktop/niri.nix @@ -0,0 +1,229 @@ +{ + inputs, + lib, + pkgs, + hostname ? null, + ... +}: + +let + isRotterdam = hostname == "rotterdam"; +in + +{ + imports = [ inputs.noctalia.homeModules.default ]; + + services.kanshi = { + enable = true; + settings = [ + { + profile.name = "default"; + profile.outputs = [ + { + criteria = "*"; + scale = 1.0; + } + ]; + } + ]; + }; + + home = { + packages = with pkgs; [ + xwayland-satellite + inputs.noctalia.packages.${pkgs.system}.default + ]; + sessionVariables.QT_QPA_PLATFORMTHEME = "gtk3"; + }; + + xdg.configFile."niri/config.kdl".text = '' + input { + keyboard { + xkb { + layout "us" + variant "altgr-intl" + } + } + touchpad { + tap + dwt + drag true + drag-lock + natural-scroll + accel-speed 0.2 + accel-profile "flat" + scroll-method "two-finger" + middle-emulation + } + mouse { + natural-scroll + accel-speed 0.2 + accel-profile "flat" + } + warp-mouse-to-focus mode="center-xy" + focus-follows-mouse + } + + layout { + gaps 8 + center-focused-column "never" + auto-center-when-space-available + preset-column-widths { + ${ + if isRotterdam then + '' + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + '' + else + '' + proportion 0.5 + proportion 1.0 + '' + } + } + default-column-width { proportion ${if isRotterdam then "0.33333" else "0.5"}; } + focus-ring { + off + } + border { + width 4 + active-color "#ffc87f" + inactive-color "#505050" + urgent-color "#9b0000" + } + tab-indicator { + width 4 + gap 4 + place-within-column + } + } + + overview { + zoom 0.65 + } + + spawn-at-startup "noctalia-shell" "-d" + layer-rule { + match namespace="^wallpaper$" + place-within-backdrop true + } + layer-rule { + match namespace="^quickshell-overview$" + place-within-backdrop true + } + + hotkey-overlay { + skip-at-startup + } + + prefer-no-csd + screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" + + animations { + slowdown 0.3 + } + + window-rule { + match app-id="zen" + default-column-width { proportion ${if isRotterdam then "0.5" else "1.0"}; } + } + + window-rule { + geometry-corner-radius 12 + clip-to-geometry true + } + + config-notification { + disable-failed + } + + binds { + Alt+Space repeat=false { spawn "vicinae" "toggle"; } + XF86AudioRaiseVolume allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "volume" "increase"; } + XF86AudioLowerVolume allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "volume" "decrease"; } + XF86AudioMute allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "volume" "muteOutput"; } + XF86MonBrightnessUp allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "brightness" "increase"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "brightness" "decrease"; } + XF86AudioPlay allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "play-pause"; } + XF86AudioStop allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "stop"; } + XF86AudioPrev allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "previous"; } + XF86AudioNext allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "next"; } + Mod+V repeat=false { spawn "vicinae" "vicinae://extensions/vicinae/clipboard/history"; } + Mod+Shift+L repeat=false { spawn "noctalia-shell" "ipc" "call" "lockScreen" "lock"; } + Mod+Return { spawn "ghostty"; } + Ctrl+Alt+Shift+A allow-when-locked=true { spawn "toggleaudiosink"; } + Mod+W repeat=false { toggle-overview; } + Mod+Q { close-window; } + Alt+Shift+Q { close-window;} + Mod+Shift+Q { close-window; } + Alt+F4 { close-window; } + Mod+Left { focus-column-left; } + Mod+Down { focus-window-or-workspace-down; } + Mod+Up { focus-window-or-workspace-up; } + Mod+Right { focus-column-right; } + Mod+H { focus-column-left; } + Mod+L { focus-column-right; } + Mod+J { focus-window-or-workspace-down; } + Mod+K { focus-window-or-workspace-up; } + Mod+Ctrl+Left { move-column-left; } + Mod+Ctrl+Down { move-window-down-or-to-workspace-down; } + Mod+Ctrl+Up { move-window-up-or-to-workspace-up; } + Mod+Ctrl+Right { move-column-right; } + Mod+Ctrl+H { move-column-left; } + Mod+Ctrl+J { move-window-down-or-to-workspace-down; } + Mod+Ctrl+K { move-window-up-or-to-workspace-up; } + Mod+Ctrl+L { move-column-right; } + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + Mod+Alt+Left { focus-monitor-left; } + Mod+Alt+Down { focus-monitor-down; } + Mod+Alt+Up { focus-monitor-up; } + Mod+Alt+Right { focus-monitor-right; } + Mod+Alt+H { focus-monitor-left; } + Mod+Alt+J { focus-monitor-down; } + Mod+Alt+K { focus-monitor-up; } + Mod+Alt+L { focus-monitor-right; } + Mod+Alt+Ctrl+Left { move-column-to-monitor-left; } + Mod+Alt+Ctrl+Down { move-column-to-monitor-down; } + Mod+Alt+Ctrl+Up { move-column-to-monitor-up; } + Mod+Alt+Ctrl+Right { move-column-to-monitor-right; } + Mod+Alt+Ctrl+H { move-column-to-monitor-left; } + Mod+Alt+Ctrl+J { move-column-to-monitor-down; } + Mod+Alt+Ctrl+K { move-column-to-monitor-up; } + Mod+Alt+Ctrl+L { move-column-to-monitor-right; } + Mod+Ctrl+U { move-workspace-down; } + Mod+Ctrl+I { move-workspace-up; } + Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } + Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; } + Mod+Shift+WheelScrollDown { focus-column-right; } + Mod+Shift+WheelScrollUp { focus-column-left; } + Mod+Ctrl+Shift+WheelScrollDown { move-column-right; } + Mod+Ctrl+Shift+WheelScrollUp { move-column-left; } + Mod+BracketLeft { consume-or-expel-window-left; } + Mod+BracketRight { consume-or-expel-window-right; } + Mod+Comma { consume-window-into-column; } + Mod+Period { expel-window-from-column; } + Mod+R { switch-preset-column-width; } + Mod+F { maximize-column; } + Mod+Ctrl+F { fullscreen-window; } + Mod+C { center-visible-columns; } + Mod+Ctrl+C { center-column; } + Mod+Space { toggle-window-floating; } + Mod+Ctrl+Space { switch-focus-between-floating-and-tiling; } + Mod+T { toggle-column-tabbed-display; } + Print { screenshot-screen; } + Mod+Print { screenshot; } + Ctrl+Print { screenshot-window; } + Mod+Backspace allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; } + Mod+Alt+E { spawn "noctalia-shell" "ipc" "call" "sessionMenu" "toggle"; } + Ctrl+Alt+Delete { spawn "noctalia-shell" "ipc" "call" "sessionMenu" "toggle"; } + Mod+Ctrl+P { power-off-monitors; } + } + ''; +} diff --git a/users/modules/direnv.nix b/users/modules/direnv.nix new file mode 100644 index 0000000..c91d0af --- /dev/null +++ b/users/modules/direnv.nix @@ -0,0 +1,8 @@ +{ pkgs, ... }: + +{ + programs.direnv = { + enable = true; + nix-direnv.enable = true; + }; +} \ No newline at end of file diff --git a/users/modules/gaming.nix b/users/modules/gaming.nix new file mode 100644 index 0000000..df33b11 --- /dev/null +++ b/users/modules/gaming.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + programs.mangohud.enable = true; +} diff --git a/users/modules/helix.nix b/users/modules/helix.nix new file mode 100644 index 0000000..a72ead3 --- /dev/null +++ b/users/modules/helix.nix @@ -0,0 +1,49 @@ +{ pkgs, ... }: + +{ + home.sessionVariables = { + EDITOR = "hx"; + }; + + programs.helix = { + enable = true; + settings = { + editor = { + file-picker.hidden = false; + idle-timeout = 0; + line-number = "relative"; + cursor-shape = { + normal = "underline"; + insert = "bar"; + select = "underline"; + }; + soft-wrap.enable = true; + auto-format = true; + indent-guides.render = true; + }; + keys.normal = { + space = { + o = "file_picker_in_current_buffer_directory"; + esc = [ + "collapse_selection" + "keep_primary_selection" + ]; + }; + }; + }; + languages = { + language = [ + { + name = "nix"; + auto-format = true; + formatter.command = "nixfmt"; + } + { + name = "typst"; + auto-format = true; + formatter.command = "typstyle -c 1000 -i"; + } + ]; + }; + }; +} diff --git a/users/modules/obs-studio.nix b/users/modules/obs-studio.nix new file mode 100644 index 0000000..67e3b8b --- /dev/null +++ b/users/modules/obs-studio.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: + +{ + programs.obs-studio = { + enable = true; + plugins = [ + pkgs.obs-studio-plugins.obs-vkcapture + pkgs.obs-studio-plugins.obs-backgroundremoval + pkgs.obs-studio-plugins.obs-pipewire-audio-capture + ]; + }; + +} diff --git a/users/modules/starship.nix b/users/modules/starship.nix new file mode 100644 index 0000000..c836c51 --- /dev/null +++ b/users/modules/starship.nix @@ -0,0 +1,40 @@ +{ pkgs, ... }: + +{ + programs.starship = { + enable = true; + enableBashIntegration = true; + enableFishIntegration = true; + settings = { + add_newline = false; + format = '' + $hostname$directory$git_branch$git_status$nix_shell + [ ❯ ](bold green) + ''; + right_format = "$cmd_duration$character"; + hostname = { + ssh_symbol = "󰖟 "; + }; + character = { + error_symbol = "[](red)"; + success_symbol = "[󱐋](green)"; + }; + cmd_duration = { + format = "[󰄉 $duration ]($style)"; + style = "yellow"; + min_time = 500; + }; + git_branch = { + symbol = " "; + style = "purple"; + }; + git_status.style = "red"; + nix_shell = { + format = "via [$symbol$state]($style)"; + heuristic = true; + style = "blue"; + symbol = "󱄅 "; + }; + }; + }; +} diff --git a/hosts/desktops/common/stylix.nix b/users/modules/stylix.nix similarity index 54% rename from hosts/desktops/common/stylix.nix rename to users/modules/stylix.nix index 3c862db..f1c7e44 100644 --- a/hosts/desktops/common/stylix.nix +++ b/users/modules/stylix.nix @@ -1,18 +1,31 @@ -{ config, pkgs, ... }: +{ + config, + inputs, + pkgs, + ... +}: { + imports = [ + inputs.stylix.homeModules.stylix + inputs.zen-browser.homeModules.beta + ]; + stylix = { enable = true; - image = pkgs.fetchurl { - url = "https://images.unsplash.com/photo-1701453831008-ea11046da960?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&dl=nat-uN9OSpSsw4A-unsplash.jpg"; - sha256 = "sha256-89o5VYI4cMP/O33oCaHi61hUYmIWEdyr8uGf/b2DMUk="; - }; - base16Scheme = "${pkgs.base16-schemes}/share/themes/catppuccin-mocha.yaml"; + polarity = "dark"; + base16Scheme = "${pkgs.base16-schemes}/share/themes/tokyodark.yaml"; cursor = { - package = pkgs.kdePackages.breeze-icons; - name = "Breeze_Light"; + package = pkgs.kdePackages.breeze; + name = "breeze_cursors"; size = 24; }; + icons = { + enable = true; + package = pkgs.morewaita-icon-theme; + light = "MoreWaita"; + dark = "MoreWaita"; + }; opacity = { applications = 1.0; desktop = 0.8; @@ -33,7 +46,7 @@ name = "FiraCode Nerd Font"; }; emoji = { - package = pkgs.noto-fonts-emoji; + package = pkgs.noto-fonts-color-emoji; name = "Noto Color Emoji"; }; sizes = { @@ -43,5 +56,14 @@ terminal = 12; }; }; + targets.zen-browser = { + enable = true; + profileNames = [ "william" ]; + }; + }; + + programs.zen-browser = { + enable = true; + profiles.william = { }; }; } diff --git a/users/modules/tmux.nix b/users/modules/tmux.nix new file mode 100644 index 0000000..4268e7a --- /dev/null +++ b/users/modules/tmux.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: + +{ + programs.tmux = { + enable = true; + clock24 = true; + terminal = "xterm-256color"; + mouse = true; + keyMode = "vi"; + }; +} \ No newline at end of file diff --git a/users/servers/user.nix b/users/servers/user.nix deleted file mode 100644 index 990167f..0000000 --- a/users/servers/user.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: - -{ - imports = [ - # Host-common imports - ../common - ]; -} diff --git a/users/user/git.nix b/users/user/git.nix new file mode 100644 index 0000000..9c1fb20 --- /dev/null +++ b/users/user/git.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: + +{ + programs = { + git = { + enable = true; + settings.user = { + name = "William"; + email = "baduhai@proton.me"; + }; + }; + diff-so-fancy = { + enable = true; + enableGitIntegration = true; + }; + }; +} diff --git a/utils.nix b/utils.nix new file mode 100644 index 0000000..8c20ab9 --- /dev/null +++ b/utils.nix @@ -0,0 +1,223 @@ +{ inputs, lib }: + +let + inherit (inputs) + self + nixpkgs + nixpkgs-stable + home-manager + agenix + ; + + # Import shared service definitions + sharedServices = import ./shared/services.nix; +in + +{ + # Re-export shared services for use in host configs + inherit (sharedServices) services; + # Tag-based host configuration system + mkHost = + { + hostname, + tags ? [ ], + system ? "x86_64-linux", + extraModules ? [ ], + }: + let + # Validate that server and desktop tags are mutually exclusive + hasServer = builtins.elem "server" tags; + hasDesktop = builtins.elem "desktop" tags; + + # Always include "common" tag implicitly + allTags = + if hasServer && hasDesktop then + throw "Error: 'server' and 'desktop' tags are mutually exclusive for host '${hostname}'" + else + [ "common" ] ++ tags; + + # Choose nixpkgs based on server tag + pkgs = if builtins.elem "server" allTags then nixpkgs-stable else nixpkgs; + + # Tag-specific modules: each tag can be either: + # 1. A file: hosts/modules/${tag}.nix + # 2. A directory: hosts/modules/${tag}/*.nix (all .nix files imported) + tagModuleFiles = builtins.concatMap ( + tag: + let + filePath = ./hosts/modules/${tag}.nix; + dirPath = ./hosts/modules/${tag}; + in + # Check if it's a file first + if builtins.pathExists filePath then + [ filePath ] + # Then check if it's a directory + else if builtins.pathExists dirPath then + let + entries = builtins.readDir dirPath; + nixFiles = pkgs.lib.filterAttrs ( + name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name + ) entries; + in + map (name: dirPath + "/${name}") (builtins.attrNames nixFiles) + else + [ ] + ) allTags; + + # Automatically import all .nix files from hosts/${hostname}/ + hostModulePath = ./hosts/${hostname}; + hostModuleFiles = + if builtins.pathExists hostModulePath then + let + entries = builtins.readDir hostModulePath; + nixFiles = pkgs.lib.filterAttrs ( + name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name && name != "${hostname}.nix" + ) entries; + in + map (name: hostModulePath + "/${name}") (builtins.attrNames nixFiles) + else + [ ]; + + # Combine all modules + allModules = [ + agenix.nixosModules.default + { + networking.hostName = hostname; + nix.nixPath = [ "nixos-config=${self.outPath}/nixosConfigurations/${hostname}" ]; + nixpkgs.overlays = [ + agenix.overlays.default + self.overlays.default + ]; + } + ] + ++ tagModuleFiles + ++ hostModuleFiles + ++ extraModules; + in + pkgs.lib.nixosSystem { + inherit system; + specialArgs = { + inherit inputs; + hostTags = allTags; + }; + modules = allModules; + }; + + # Tag-based user configuration system + mkHome = + { + username, + hostname ? null, + homeDirectory ? "/home/${username}", + tags ? [ ], + extraModules ? [ ], + }: + let + pkgs = nixpkgs.legacyPackages.x86_64-linux; + + # Always include "common" tag implicitly + allTags = [ "common" ] ++ tags; + + # Tag-specific modules: each tag maps to users/modules/${tag}.nix if it exists + tagModuleFiles = builtins.concatMap ( + tag: + let + filePath = ./users/modules/${tag}.nix; + dirPath = ./users/modules/${tag}; + in + # Check if it's a file first + if builtins.pathExists filePath then + [ filePath ] + # Then check if it's a directory + else if builtins.pathExists dirPath then + let + entries = builtins.readDir dirPath; + nixFiles = pkgs.lib.filterAttrs ( + name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name + ) entries; + in + map (name: dirPath + "/${name}") (builtins.attrNames nixFiles) + else + [ ] + ) allTags; + + # Automatically import all .nix files from users/${username}/ + userModulePath = ./users/${username}; + userModuleFiles = + if builtins.pathExists userModulePath then + let + entries = builtins.readDir userModulePath; + nixFiles = pkgs.lib.filterAttrs ( + name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name + ) entries; + in + map (name: userModulePath + "/${name}") (builtins.attrNames nixFiles) + else + [ ]; + + # Combine all modules + allModules = [ + { + home = { + inherit username homeDirectory; + stateVersion = "22.05"; + }; + } + ] + ++ tagModuleFiles + ++ userModuleFiles + ++ extraModules; + in + home-manager.lib.homeManagerConfiguration { + inherit pkgs; + extraSpecialArgs = { + inherit inputs hostname; + userTags = allTags; + }; + modules = allModules ++ [ + { + nixpkgs.overlays = [ self.overlays.default ]; + } + ]; + }; + + # Nginx virtual host utilities + mkNginxVHosts = + { domains }: + let + # Extract domain name and apply it as useACMEHost + mkVHostConfig = domain: config: + lib.recursiveUpdate { + useACMEHost = domain; + forceSSL = true; + kTLS = true; + } config; + in + lib.mapAttrs mkVHostConfig domains; + + # Split DNS utilities for unbound + # Generates unbound view config from a list of DNS entries + mkSplitDNS = + entries: + let + # Generate local-data entries for all domains + tailscaleData = map (e: ''"${e.domain}. IN A ${e.tailscaleIP}"'') entries; + lanData = map (e: ''"${e.domain}. IN A ${e.lanIP}"'') entries; + in + [ + # Single Tailscale view with all domains + { + name = "tailscale"; + view-first = true; + local-zone = ''"baduhai.dev." transparent''; + local-data = tailscaleData; + } + # Single LAN view with all domains + { + name = "lan"; + view-first = true; + local-zone = ''"baduhai.dev." transparent''; + local-data = lanData; + } + ]; +}