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 aefdd3e..27c3580 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1747575206, - "narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=", + "lastModified": 1761656077, + "narHash": "sha256-lsNWuj4Z+pE7s0bd2OKicOFq9bK86JE0ZGeKJbNqb94=", "owner": "ryantm", "repo": "agenix", - "rev": "4835b1dc898959d8547a871ef484930675cb47f1", + "rev": "9ba0d85de3eaa7afeab493fed622008b6e4924f5", "type": "github" }, "original": { @@ -23,6 +23,96 @@ "type": "github" } }, + "base16": { + "inputs": { + "fromYaml": "fromYaml" + }, + "locked": { + "lastModified": 1755819240, + "narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=", + "owner": "SenchoPens", + "repo": "base16.nix", + "rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "base16.nix", + "type": "github" + } + }, + "base16-fish": { + "flake": false, + "locked": { + "lastModified": 1754405784, + "narHash": "sha256-l9xHIy+85FN+bEo6yquq2IjD1rSg9fjfjpyGP1W8YXo=", + "owner": "tomyun", + "repo": "base16-fish", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", + "type": "github" + }, + "original": { + "owner": "tomyun", + "repo": "base16-fish", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", + "type": "github" + } + }, + "base16-helix": { + "flake": false, + "locked": { + "lastModified": 1752979451, + "narHash": "sha256-0CQM+FkYy0fOO/sMGhOoNL80ftsAzYCg9VhIrodqusM=", + "owner": "tinted-theming", + "repo": "base16-helix", + "rev": "27cf1e66e50abc622fb76a3019012dc07c678fac", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-helix", + "type": "github" + } + }, + "base16-vim": { + "flake": false, + "locked": { + "lastModified": 1732806396, + "narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=", + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + } + }, + "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": [ @@ -48,17 +138,15 @@ "deploy-rs": { "inputs": { "flake-compat": "flake-compat", - "nixpkgs": [ - "nixpkgs-stable" - ], + "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": { @@ -69,33 +157,46 @@ }, "disko": { "inputs": { - "nixpkgs": [ - "nixpkgs-stable" - ] + "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1736864502, - "narHash": "sha256-ItkIZyebGvNH2dK9jVGzJHGPtb6BSWLN8Gmef16NeY0=", + "lastModified": 1761899396, + "narHash": "sha256-XOpKBp6HLzzMCbzW50TEuXN35zN5WGQREC7n34DcNMM=", "owner": "nix-community", "repo": "disko", - "rev": "0141aabed359f063de7413f80d906e1d98c0c123", + "rev": "6f4cf5abbe318e4cd1e879506f6eeafd83f7b998", "type": "github" }, "original": { "owner": "nix-community", - "ref": "v1.11.0", "repo": "disko", "type": "github" } }, + "firefox-gnome-theme": { + "flake": false, + "locked": { + "lastModified": 1758112371, + "narHash": "sha256-lizRM2pj6PHrR25yimjyFn04OS4wcdbc38DCdBVa2rk=", + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "rev": "0909cfe4a2af8d358ad13b20246a350e14c2473d", + "type": "github" + }, + "original": { + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", "type": "github" }, "original": { @@ -104,6 +205,151 @@ "type": "github" } }, + "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": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "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": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_8" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "fromYaml": { + "flake": false, + "locked": { + "lastModified": 1731966426, + "narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=", + "owner": "SenchoPens", + "repo": "fromYaml", + "rev": "106af9e2f715e2d828df706c386a685698f3223b", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "fromYaml", + "type": "github" + } + }, + "gnome-shell": { + "flake": false, + "locked": { + "lastModified": 1748186689, + "narHash": "sha256-UaD7Y9f8iuLBMGHXeJlRu6U1Ggw5B9JnkFs3enZlap0=", + "owner": "GNOME", + "repo": "gnome-shell", + "rev": "8c88f917db0f1f0d80fa55206c863d3746fa18d0", + "type": "github" + }, + "original": { + "owner": "GNOME", + "ref": "48.2", + "repo": "gnome-shell", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -125,27 +371,6 @@ "type": "github" } }, - "home-manager-stable": { - "inputs": { - "nixpkgs": [ - "nixpkgs-stable" - ] - }, - "locked": { - "lastModified": 1748665073, - "narHash": "sha256-RMhjnPKWtCoIIHiuR9QKD7xfsKb3agxzMfJY8V9MOew=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "282e1e029cb6ab4811114fc85110613d72771dea", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "release-25.05", - "repo": "home-manager", - "type": "github" - } - }, "home-manager_2": { "inputs": { "nixpkgs": [ @@ -153,11 +378,11 @@ ] }, "locked": { - "lastModified": 1748830238, - "narHash": "sha256-EB+LzYHK0D5aqxZiYoPeoZoOzSAs8eqBDxm3R+6wMKU=", + "lastModified": 1762178366, + "narHash": "sha256-I+8yE5HVR2SFcHnW0771psQ/zn0qVzsKHY/gUM0nEVM=", "owner": "nix-community", "repo": "home-manager", - "rev": "c7fdb7e90bff1a51b79c1eed458fb39e6649a82a", + "rev": "8c824254b1ed9e797f6235fc3c62f365893c561a", "type": "github" }, "original": { @@ -167,6 +392,27 @@ "type": "github" } }, + "home-manager_3": { + "inputs": { + "nixpkgs": [ + "zen-browser", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1752603129, + "narHash": "sha256-S+wmHhwNQ5Ru689L2Gu8n1OD6s9eU9n9mD827JNR+kw=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "e8c19a3cec2814c754f031ab3ae7316b64da085b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, "impermanence": { "locked": { "lastModified": 1737831083, @@ -182,45 +428,233 @@ "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": 1739444422, - "narHash": "sha256-iAVVHi7X3kWORftY+LVbRiStRnQEob2TULWyjMS6dWg=", + "lastModified": 1754777568, + "narHash": "sha256-0bBqT+3XncgF8F03RFAamw9vdf0VmaDoIJLTGkjfQZs=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "5e54c3ca05a7c7d968ae1ddeabe01d2a9bc1e177", + "rev": "62f636b87ef6050760a8cb325cadb90674d1e23e", "type": "github" }, "original": { "owner": "gmodena", - "ref": "latest", + "ref": "main", "repo": "nix-flatpak", "type": "github" } }, + "nix-index-database": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762055842, + "narHash": "sha256-Pu1v3mlFhRzZiSxVHb2/i/f5yeYyRNqr0RvEUJ4UgHo=", + "owner": "nix-community", + "repo": "nix-index-database", + "rev": "359ff6333a7b0b60819d4c20ed05a3a1f726771f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-index-database", + "type": "github" + } + }, + "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", + "nix-options-doc": "nix-options-doc", + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "lastModified": 1761970410, + "narHash": "sha256-IUm2nkbKlDkG94ruTmIYLERpBn6gXydm3scZIKzpcKs=", + "owner": "nix-community", + "repo": "nixos-cli", + "rev": "5c259f72ae1eaa00b99354d81130d8fddb7f9a7a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-cli", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1748693115, - "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=", - "owner": "nixos", + "lastModified": 1743014863, + "narHash": "sha256-jAIUqsiN2r3hCuHji80U7NNEafpIMBXiwKlSrjWMlpg=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc", + "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": 1748708770, - "narHash": "sha256-q8jG2HJWgooWa9H0iatZqBPF3bp0504e05MevFmnFLY=", + "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": "a59eb7800787c926045d51b70982ae285faa2346", + "rev": "3de8f8d73e35724bf9abef41f1bdbedda1e14a31", "type": "github" }, "original": { @@ -230,17 +664,330 @@ "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": 1752596105, + "narHash": "sha256-lFNVsu/mHLq3q11MuGkMhUUoSXEdQjCHvpReaGP1S2k=", + "owner": "NixOS", + "repo": "nixpkgs", + "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": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "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", "impermanence": "impermanence", + "niri": "niri", + "niri-flake": "niri-flake", + "nix-ai-tools": "nix-ai-tools", "nix-flatpak": "nix-flatpak", - "nixpkgs": "nixpkgs", - "nixpkgs-stable": "nixpkgs-stable" + "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": { + "inputs": { + "base16": "base16", + "base16-fish": "base16-fish", + "base16-helix": "base16-helix", + "base16-vim": "base16-vim", + "firefox-gnome-theme": "firefox-gnome-theme", + "flake-parts": "flake-parts_2", + "gnome-shell": "gnome-shell", + "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": 1762101397, + "narHash": "sha256-wGiL2K3kAyBBmIZpJEskaSIgyzzpg0zwfvri+Sy6/CI=", + "owner": "danth", + "repo": "stylix", + "rev": "8c0640d5722a02178c8ee80a62c5f019cab4b3c1", + "type": "github" + }, + "original": { + "owner": "danth", + "repo": "stylix", + "type": "github" } }, "systems": { @@ -273,16 +1020,230 @@ "type": "github" } }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "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": { + "lastModified": 1726913040, + "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=", + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + } + }, + "tinted-kitty": { + "flake": false, + "locked": { + "lastModified": 1735730497, + "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=", + "owner": "tinted-theming", + "repo": "tinted-kitty", + "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-kitty", + "type": "github" + } + }, + "tinted-schemes": { + "flake": false, + "locked": { + "lastModified": 1757716333, + "narHash": "sha256-d4km8W7w2zCUEmPAPUoLk1NlYrGODuVa3P7St+UrqkM=", + "owner": "tinted-theming", + "repo": "schemes", + "rev": "317a5e10c35825a6c905d912e480dfe8e71c7559", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "schemes", + "type": "github" + } + }, + "tinted-tmux": { + "flake": false, + "locked": { + "lastModified": 1757811970, + "narHash": "sha256-n5ZJgmzGZXOD9pZdAl1OnBu3PIqD+X3vEBUGbTi4JiI=", + "owner": "tinted-theming", + "repo": "tinted-tmux", + "rev": "d217ba31c846006e9e0ae70775b0ee0f00aa6b1e", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-tmux", + "type": "github" + } + }, + "tinted-zed": { + "flake": false, + "locked": { + "lastModified": 1757811247, + "narHash": "sha256-4EFOUyLj85NRL3OacHoLGEo0wjiRJzfsXtR4CZWAn6w=", + "owner": "tinted-theming", + "repo": "base16-zed", + "rev": "824fe0aacf82b3c26690d14e8d2cedd56e18404e", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-zed", + "type": "github" + } + }, + "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": { @@ -290,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 b86c103..c5c3880 100644 --- a/flake.nix +++ b/flake.nix @@ -2,6 +2,8 @@ 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-25.05"; @@ -9,186 +11,67 @@ url = "github:nix-community/home-manager/master"; inputs.nixpkgs.follows = "nixpkgs"; }; - home-manager-stable = { - url = "github:nix-community/home-manager/release-25.05"; - inputs.nixpkgs.follows = "nixpkgs-stable"; - }; - - disko = { - url = "github:nix-community/disko?ref=v1.11.0"; - inputs.nixpkgs.follows = "nixpkgs-stable"; - }; agenix = { url = "github:ryantm/agenix"; inputs.nixpkgs.follows = "nixpkgs-stable"; }; - deploy-rs = { - url = "github:serokell/deploy-rs"; - inputs.nixpkgs.follows = "nixpkgs-stable"; + disko.url = "github:nix-community/disko"; + + noctalia = { + url = "github:noctalia-dev/noctalia-shell"; + inputs.nixpkgs.follows = "nixpkgs"; }; - nix-flatpak.url = "github:gmodena/nix-flatpak/latest"; + 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, - disko, - agenix, - deploy-rs, - nix-flatpak, - impermanence, - ... - }: - { - nixosConfigurations = - let - mkHost = - { - hostname, - type, # workstation|server - system ? "x86_64-linux", - extraModules ? [ ], - }: - let - pkgs = if type == "server" then nixpkgs-stable else nixpkgs; - hm = if type == "server" then home-manager-stable else home-manager; - hostTypeFlags = { - isServer = type == "server"; - isWorkstation = type == "workstation"; - }; - defaultModules = [ - ./hosts/${hostname}.nix - agenix.nixosModules.default - disko.nixosModules.default - hm.nixosModules.default - impermanence.nixosModules.impermanence - nix-flatpak.nixosModules.nix-flatpak - { - nixpkgs.overlays = [ - agenix.overlays.default - ]; - } - ]; - workstationModules = [ - { - nixpkgs.overlays = [ - self.overlays.workstationOverlay - ]; - } - ]; - serverModules = [ - { - nixpkgs.overlays = [ - self.overlays.serverOverlay - ]; - } - ]; - typeModules = if type == "server" then serverModules else workstationModules; - allModules = defaultModules ++ typeModules ++ extraModules; - in - pkgs.lib.nixosSystem { - inherit system; - specialArgs = { - inherit inputs; - hostType = hostTypeFlags; - }; - modules = allModules; - }; - in - { - rotterdam = mkHost { - hostname = "rotterdam"; - type = "workstation"; - }; - io = mkHost { - hostname = "io"; - type = "workstation"; - }; - alexandria = mkHost { - hostname = "alexandria"; - type = "server"; - extraModules = [ self.nixosModules.qbittorrent ]; - }; - trantor = mkHost { - hostname = "trantor"; - type = "server"; - system = "aarch64-linux"; - }; - }; + inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; - overlays = { - overlay = final: prev: { - }; - workstationOverlay = final: prev: { - plasticity = nixpkgs.legacyPackages."x86_64-linux".callPackage ./packages/plasticity.nix { }; - toggleaudiosink = - nixpkgs.legacyPackages."x86_64-linux".callPackage ./packages/toggleaudiosink.nix - { }; - }; - serverOverlay = final: prev: { - }; - }; - - 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; - }; - }; - }; - - trantor = { - hostname = "trantor"; - 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/alexandria.nix b/hosts/alexandria.nix deleted file mode 100644 index 6050904..0000000 --- a/hosts/alexandria.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ ... }: - -{ - networking.hostName = "alexandria"; - - imports = [ - ./modules/alexandria - ./modules - ]; - - nix.nixPath = [ "nixos-config=${./alexandria.nix}" ]; -} diff --git a/hosts/modules/alexandria/hardware-configuration.nix b/hosts/alexandria/hardware-configuration.nix similarity index 100% rename from hosts/modules/alexandria/hardware-configuration.nix rename to hosts/alexandria/hardware-configuration.nix 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/modules/alexandria/nextcloud.nix b/hosts/alexandria/nextcloud.nix similarity index 67% rename from hosts/modules/alexandria/nextcloud.nix rename to hosts/alexandria/nextcloud.nix index 456f88c..c449cce 100644 --- a/hosts/modules/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.nextcloud31; + 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/io.nix b/hosts/io.nix deleted file mode 100644 index 3910dc1..0000000 --- a/hosts/io.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ ... }: - -{ - networking.hostName = "io"; - - imports = [ - ./modules/io - ./modules - ]; - - nix.nixPath = [ "nixos-config=${./io.nix}" ]; -} diff --git a/hosts/modules/io/boot.nix b/hosts/io/boot.nix similarity index 97% rename from hosts/modules/io/boot.nix rename to hosts/io/boot.nix index 1580753..326f7dc 100644 --- a/hosts/modules/io/boot.nix +++ b/hosts/io/boot.nix @@ -1,5 +1,3 @@ -{ ... }: - { boot = { # TODO check if future kernel versions fix boot issue with systemd initrd with tpm 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/modules/io/programs.nix b/hosts/io/programs.nix similarity index 73% rename from hosts/modules/io/programs.nix rename to hosts/io/programs.nix index f1286c7..e272d22 100644 --- a/hosts/modules/io/programs.nix +++ b/hosts/io/programs.nix @@ -19,19 +19,9 @@ in { environment = { systemPackages = with pkgs; [ - arduino-ide - esptool - # fritzing 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"; - }; - }; } diff --git a/hosts/modules/io/services.nix b/hosts/io/services.nix similarity index 81% rename from hosts/modules/io/services.nix rename to hosts/io/services.nix index 5291695..df41a6f 100644 --- a/hosts/modules/io/services.nix +++ b/hosts/io/services.nix @@ -1,4 +1,4 @@ -{ ... }: +{ pkgs, ... }: { services = { @@ -48,5 +48,14 @@ }; }; }; + 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/alexandria/changedetection.nix b/hosts/modules/alexandria/changedetection.nix deleted file mode 100644 index 702952f..0000000 --- a/hosts/modules/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/modules/alexandria/cinny.nix b/hosts/modules/alexandria/cinny.nix deleted file mode 100644 index fc4770f..0000000 --- a/hosts/modules/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/modules/alexandria/default.nix b/hosts/modules/alexandria/default.nix deleted file mode 100644 index 2816fef..0000000 --- a/hosts/modules/alexandria/default.nix +++ /dev/null @@ -1,49 +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 - # ./nextcloud.nix - ./nginx.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/modules/alexandria/forgejo.nix b/hosts/modules/alexandria/forgejo.nix deleted file mode 100644 index a51c050..0000000 --- a/hosts/modules/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/modules/alexandria/jellyfin.nix b/hosts/modules/alexandria/jellyfin.nix deleted file mode 100644 index 015f4aa..0000000 --- a/hosts/modules/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/modules/alexandria/librespeed.nix b/hosts/modules/alexandria/librespeed.nix deleted file mode 100644 index 6b830b7..0000000 --- a/hosts/modules/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/modules/alexandria/memos.nix b/hosts/modules/alexandria/memos.nix deleted file mode 100644 index 2d41cc0..0000000 --- a/hosts/modules/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/modules/alexandria/networking.nix b/hosts/modules/alexandria/networking.nix deleted file mode 100644 index 722303c..0000000 --- a/hosts/modules/alexandria/networking.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ ... }: - -{ - networking = { - firewall = { - allowedTCPPorts = [ - 80 # HTTP - 443 # HTTPS - 25565 # Minecraft - ]; - allowedUDPPorts = [ - 19132 # Minecraft Bedrock - 25565 # Minecraft - ]; - }; - }; -} diff --git a/hosts/modules/alexandria/nginx.nix b/hosts/modules/alexandria/nginx.nix deleted file mode 100644 index 5075bcf..0000000 --- a/hosts/modules/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/modules/alexandria/searx.nix b/hosts/modules/alexandria/searx.nix deleted file mode 100644 index 94f3017..0000000 --- a/hosts/modules/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/modules/alexandria/services.nix b/hosts/modules/alexandria/services.nix deleted file mode 100644 index a9350f6..0000000 --- a/hosts/modules/alexandria/services.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ ... }: - -{ - services.postgresql.enable = true; - - # TODO: remove when bug fix - # serokell/deploy-rs/issues/57 - # NixOS/nixpkgs/issues/180175 - # Workaround for upstream bug in NetworkManager-wait-online.service - systemd.services.NetworkManager-wait-online.enable = false; -} diff --git a/hosts/modules/alexandria/users.nix b/hosts/modules/alexandria/users.nix deleted file mode 100644 index 353f28f..0000000 --- a/hosts/modules/alexandria/users.nix +++ /dev/null @@ -1,19 +0,0 @@ -{ ... }: - -{ - users = { - users = { - nginx.extraGroups = [ "acme" ]; - }; - groups = { - hosted = { - gid = 1005; - members = [ - "user" - "paperless" - "vaultwarden" - ]; - }; - }; - }; -} diff --git a/hosts/modules/alexandria/vaultwarden.nix b/hosts/modules/alexandria/vaultwarden.nix deleted file mode 100644 index 2207c08..0000000 --- a/hosts/modules/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/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/modules/boot.nix b/hosts/modules/boot.nix deleted file mode 100644 index 8677186..0000000 --- a/hosts/modules/boot.nix +++ /dev/null @@ -1,61 +0,0 @@ -{ - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - boot = { - loader = { - timeout = 1; - efi.canTouchEfiVariables = true; - systemd-boot = { - enable = true; - editor = false; - consoleMode = "max"; - sortKey = "aa"; - netbootxyz = { - enable = true; - sortKey = "zz"; - }; - }; - }; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - boot.kernelPackages = pkgs.linuxPackages_hardened; - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - boot = { - plymouth.enable = true; - initrd.systemd.enable = true; - loader.efi.efiSysMountPoint = "/boot/efi"; - kernelPackages = pkgs.linuxPackages_xanmod_latest; - extraModprobeConfig = '' - options bluetooth disable_ertm=1 - ''; - kernel.sysctl = { - "net.ipv4.tcp_mtu_probing" = 1; - }; - kernelParams = [ - "quiet" - "splash" - "i2c-dev" - "i2c-piix4" - "loglevel=3" - "udev.log_priority=3" - "rd.udev.log_level=3" - "rd.systemd.show_status=false" - ]; - }; - }) - ]; -} diff --git a/hosts/modules/common/boot.nix b/hosts/modules/common/boot.nix new file mode 100644 index 0000000..fbba278 --- /dev/null +++ b/hosts/modules/common/boot.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: + +{ + boot = { + loader = { + timeout = 1; + efi.canTouchEfiVariables = true; + systemd-boot = { + enable = true; + editor = false; + consoleMode = "max"; + sortKey = "aa"; + netbootxyz = { + enable = true; + sortKey = "zz"; + }; + }; + }; + }; +} diff --git a/hosts/modules/common/console.nix b/hosts/modules/common/console.nix new file mode 100644 index 0000000..9cb99d4 --- /dev/null +++ b/hosts/modules/common/console.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + console = { + useXkbConfig = true; + earlySetup = true; + }; +} diff --git a/hosts/modules/common/firewall.nix b/hosts/modules/common/firewall.nix new file mode 100644 index 0000000..910e803 --- /dev/null +++ b/hosts/modules/common/firewall.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + networking = { + firewall.enable = true; + nftables.enable = true; + }; +} diff --git a/hosts/modules/common/locale.nix b/hosts/modules/common/locale.nix new file mode 100644 index 0000000..1171a32 --- /dev/null +++ b/hosts/modules/common/locale.nix @@ -0,0 +1,21 @@ +{ ... }: + +{ + time.timeZone = "America/Bahia"; + + i18n = { + 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"; + LC_NAME = "pt_BR.utf8"; + LC_NUMERIC = "pt_BR.utf8"; + LC_PAPER = "pt_BR.utf8"; + LC_TELEPHONE = "pt_BR.utf8"; + LC_TIME = "en_IE.utf8"; + }; + }; +} diff --git a/hosts/modules/common/nix.nix b/hosts/modules/common/nix.nix new file mode 100644 index 0000000..5ef9c4c --- /dev/null +++ b/hosts/modules/common/nix.nix @@ -0,0 +1,38 @@ +{ inputs, ... }: + +{ + imports = [ inputs.nixos-cli.nixosModules.nixos-cli ]; + + nix = { + settings = { + auto-optimise-store = true; + connect-timeout = 10; + log-lines = 25; + min-free = 128000000; + max-free = 1000000000; + trusted-users = [ "@wheel" ]; + }; + extraOptions = "experimental-features = nix-command flakes"; + gc = { + automatic = true; + options = "--delete-older-than 8d"; + }; + }; + + nixpkgs.config = { + allowUnfree = true; + enableParallelBuilding = true; + buildManPages = false; + 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/modules/common/security.nix b/hosts/modules/common/security.nix new file mode 100644 index 0000000..33d4953 --- /dev/null +++ b/hosts/modules/common/security.nix @@ -0,0 +1,13 @@ +{ ... }: + +{ + security = { + unprivilegedUsernsClone = true; # Needed for rootless podman + sudo = { + wheelNeedsPassword = false; + extraConfig = '' + Defaults lecture = never + ''; + }; + }; +} 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/modules/common/users.nix b/hosts/modules/common/users.nix new file mode 100644 index 0000000..7dd6490 --- /dev/null +++ b/hosts/modules/common/users.nix @@ -0,0 +1,24 @@ +{ pkgs, ... }: + +{ + users.users = { + user = { + isNormalUser = true; + shell = pkgs.fish; + extraGroups = [ + "networkmanager" + "wheel" + ]; + openssh.authorizedKeys.keys = [ + "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; + hashedPassword = "!"; + }; + }; +} diff --git a/hosts/modules/console.nix b/hosts/modules/console.nix deleted file mode 100644 index 042976d..0000000 --- a/hosts/modules/console.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ hostType, lib, ... }: - -{ - config = lib.mkMerge [ - # Common configuration - { - console = { - useXkbConfig = true; - earlySetup = true; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - }) - ]; -} diff --git a/hosts/modules/default.nix b/hosts/modules/default.nix deleted file mode 100644 index bc290b2..0000000 --- a/hosts/modules/default.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./console.nix - ./desktop.nix - ./impermanence.nix - ./locale.nix - ./networking.nix - ./nix.nix - ./programs.nix - ./security.nix - ./services.nix - ./users.nix - ./virtualisation.nix - ]; -} diff --git a/hosts/modules/desktop.nix b/hosts/modules/desktop.nix deleted file mode 100644 index 2ac53c4..0000000 --- a/hosts/modules/desktop.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - 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 = "${pkgs.greetd.tuigreet}/bin/tuigreet --remember --asterisks --time"; - }; - }; - programs.niri.enable = true; - environment.systemPackages = with pkgs; [ - anyrun - foot - gsettings-desktop-schemas - swaybg - swww - xwayland-satellite - ]; - - 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 - - xdg.portal = { - enable = true; - xdgOpenUsePortal = true; - extraPortals = with pkgs; [ - xdg-desktop-portal-gtk - xdg-desktop-portal-gnome - ]; - }; - }) - ]; -} diff --git a/hosts/modules/desktop/boot.nix b/hosts/modules/desktop/boot.nix new file mode 100644 index 0000000..0ac4847 --- /dev/null +++ b/hosts/modules/desktop/boot.nix @@ -0,0 +1,26 @@ +{ pkgs, ... }: + +{ + boot = { + plymouth.enable = true; + initrd.systemd.enable = true; + loader.efi.efiSysMountPoint = "/boot/efi"; + kernelPackages = pkgs.linuxPackages_xanmod_latest; + extraModprobeConfig = '' + options bluetooth disable_ertm=1 + ''; + kernel.sysctl = { + "net.ipv4.tcp_mtu_probing" = 1; + }; + kernelParams = [ + "quiet" + "splash" + "i2c-dev" + "i2c-piix4" + "loglevel=3" + "udev.log_priority=3" + "rd.udev.log_level=3" + "rd.systemd.show_status=false" + ]; + }; +} 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/modules/desktop/nix.nix b/hosts/modules/desktop/nix.nix new file mode 100644 index 0000000..54a3549 --- /dev/null +++ b/hosts/modules/desktop/nix.nix @@ -0,0 +1,13 @@ +{ inputs, ... }: + +{ + environment.etc."channels/nixpkgs".source = inputs.nixpkgs.outPath; + + nix = { + registry.nixpkgs.flake = inputs.nixpkgs; + nixPath = [ + "nixpkgs=${inputs.nixpkgs}" + "/nix/var/nix/profiles/per-user/root/channels" + ]; + }; +} diff --git a/hosts/modules/desktop/services.nix b/hosts/modules/desktop/services.nix new file mode 100644 index 0000000..66b78f1 --- /dev/null +++ b/hosts/modules/desktop/services.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: + +{ + services = { + printing.enable = true; + udev.packages = with pkgs; [ yubikey-personalization ]; + keyd = { + enable = true; + keyboards.all = { + ids = [ "*" ]; + settings.main.capslock = "overload(meta, esc)"; + }; + }; + }; +} 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/modules/environment.nix b/hosts/modules/environment.nix deleted file mode 100644 index a67ca90..0000000 --- a/hosts/modules/environment.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ pkgs, ... }: - -{ -} diff --git a/hosts/modules/ephemeral.nix b/hosts/modules/ephemeral.nix new file mode 100644 index 0000000..cad5f41 --- /dev/null +++ b/hosts/modules/ephemeral.nix @@ -0,0 +1,41 @@ +{ 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 = [ + "/etc/machine-id" + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + "/etc/ssh/ssh_host_rsa_key" + "/etc/ssh/ssh_host_rsa_key.pub" + ]; + directories = [ + "/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/impermanence.nix b/hosts/modules/impermanence.nix deleted file mode 100644 index 7c5c7d6..0000000 --- a/hosts/modules/impermanence.nix +++ /dev/null @@ -1,41 +0,0 @@ -{ - hostType, - lib, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - environment.persistence.main = { - persistentStoragePath = "/persistent"; - files = [ - "/etc/machine-id" - "/etc/ssh/ssh_host_ed25519_key" - "/etc/ssh/ssh_host_ed25519_key.pub" - "/etc/ssh/ssh_host_rsa_key" - "/etc/ssh/ssh_host_rsa_key.pub" - ]; - directories = [ - "/etc/NetworkManager/system-connections" - "/var/lib/bluetooth" - "/var/lib/flatpak" - "/var/lib/nixos" - "/var/lib/systemd/coredump" - "/var/lib/systemd/timers" - "/var/lib/tailscale" - "/var/log" - ]; - }; - }) - ]; -} diff --git a/hosts/modules/io/default.nix b/hosts/modules/io/default.nix deleted file mode 100644 index aac6e12..0000000 --- a/hosts/modules/io/default.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./ephermal.nix - ./hardware-configuration.nix - ./programs.nix - ./services.nix - ]; -} diff --git a/hosts/modules/io/ephermal.nix b/hosts/modules/io/ephermal.nix deleted file mode 100644 index 35542f8..0000000 --- a/hosts/modules/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/modules/io/hardware-configuration.nix b/hosts/modules/io/hardware-configuration.nix deleted file mode 100644 index 020240f..0000000 --- a/hosts/modules/io/hardware-configuration.nix +++ /dev/null @@ -1,88 +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" - ]; - }; - }; - - 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/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/locale.nix b/hosts/modules/locale.nix deleted file mode 100644 index 44204d5..0000000 --- a/hosts/modules/locale.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ hostType, lib, ... }: - -{ - config = lib.mkMerge [ - # Common configuration - { - time.timeZone = "America/Bahia"; - - i18n = { - defaultLocale = "en_US.UTF-8"; - extraLocaleSettings = { - LC_ADDRESS = "pt_BR.utf8"; - LC_IDENTIFICATION = "pt_BR.utf8"; - LC_MEASUREMENT = "pt_BR.utf8"; - LC_MONETARY = "pt_BR.utf8"; - LC_NAME = "pt_BR.utf8"; - LC_NUMERIC = "pt_BR.utf8"; - LC_PAPER = "pt_BR.utf8"; - LC_TELEPHONE = "pt_BR.utf8"; - LC_TIME = "en_IE.utf8"; - }; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - }) - ]; -} diff --git a/hosts/modules/networking.nix b/hosts/modules/networking.nix deleted file mode 100644 index 30dd7b5..0000000 --- a/hosts/modules/networking.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ - hostType, - lib, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - networking = { - networkmanager.enable = true; - firewall.enable = true; - }; - - services = { - tailscale = { - enable = true; - extraUpFlags = [ "--operator=user" ]; - }; - openssh = { - enable = true; - settings.PermitRootLogin = "no"; - }; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - services.tailscale = { - extraSetFlags = [ "--advertise-exit-node" ]; - useRoutingFeatures = "server"; - }; - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - }) - ]; -} 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/modules/nix.nix b/hosts/modules/nix.nix deleted file mode 100644 index ddc3b5b..0000000 --- a/hosts/modules/nix.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ - inputs, - lib, - hostType, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - nix = { - settings = { - auto-optimise-store = true; - connect-timeout = 10; - log-lines = 25; - min-free = 128000000; - max-free = 1000000000; - trusted-users = [ "@wheel" ]; - }; - extraOptions = "experimental-features = nix-command flakes"; - gc = { - automatic = true; - options = "--delete-older-than 8d"; - }; - }; - - nixpkgs.config = { - allowUnfree = true; - enableParallelBuilding = true; - buildManPages = false; - buildDocs = false; - }; - - system.stateVersion = "22.11"; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - environment.etc."channels/nixpkgs".source = inputs.nixpkgs-stable.outPath; - - nix = { - registry.nixpkgs.flake = inputs.nixpkgs-stable; - nixPath = [ - "nixpkgs=/etc/channels/nixpkgs" - "/nix/var/nix/profiles/per-user/root/channels" - ]; - }; - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - environment.etc."channels/nixpkgs".source = inputs.nixpkgs.outPath; - - nix = { - registry.nixpkgs.flake = inputs.nixpkgs; - nixPath = [ - "nixpkgs=${inputs.nixpkgs}" - "/nix/var/nix/profiles/per-user/root/channels" - ]; - }; - }) - ]; -} diff --git a/hosts/modules/podman.nix b/hosts/modules/podman.nix new file mode 100644 index 0000000..99018cc --- /dev/null +++ b/hosts/modules/podman.nix @@ -0,0 +1,14 @@ +{ pkgs, ... }: + +{ + virtualisation.podman = { + enable = true; + autoPrune.enable = true; + extraPackages = [ pkgs.podman-compose ]; + }; + + systemd = { + services.podman-auto-update.enable = true; + timers.podman-auto-update.enable = true; + }; +} diff --git a/hosts/modules/programs.nix b/hosts/modules/programs.nix deleted file mode 100644 index 5253677..0000000 --- a/hosts/modules/programs.nix +++ /dev/null @@ -1,164 +0,0 @@ -{ - hostType, - inputs, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - environment.systemPackages = with pkgs; [ - ### Dev Tools ### - agenix - git - helix - ### System Utilities ### - btop - fastfetch - nixos-firewall-tool - sysz - wget - tmux - ]; - - programs = { - fish.enable = true; - command-not-found.enable = false; - }; - - 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"; - }; - - services.flatpak.enable = lib.mkDefault false; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation ({ - environment.systemPackages = with pkgs; [ - ### Dev Tools ### - bat - deploy-rs - fd - fzf - nixfmt-rfc-style - nix-init - nix-output-monitor - ripgrep - ### Internet Browsers & Communication ### - beeper - brave - tor-browser - vesktop - ### Office & Productivity ### - aspell - aspellDicts.de - aspellDicts.en - aspellDicts.en-computers - aspellDicts.pt_BR - libreoffice-qt - obsidian - (octaveFull.withPackages (octavePackages: with octavePackages; [ signal ])) - onlyoffice-desktopeditors - rnote - ### Graphics & Design ### - gimp - inkscape - orca-slicer - plasticity - ### Gaming & Entertainment ### - clonehero - heroic - mangohud - prismlauncher - ### System Utilities ### - adwaita-icon-theme - junction - kara - kde-rounded-corners - libfido2 - morewaita-icon-theme - nautilus - mission-center - p7zip - qbittorrent - quickemu - quickgui - rustdesk - steam-run - toggleaudiosink - unrar - ### Media ### - mpv - obs-studio - qview - ]; - - programs = { - adb.enable = true; - steam = { - enable = true; - extraCompatPackages = [ pkgs.proton-ge-bin ]; - }; - dconf.enable = true; - nix-ld.enable = true; - kdeconnect.enable = true; - partition-manager.enable = true; - gamemode.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 - inter - nerd-fonts.hack - noto-fonts-cjk-sans - roboto - ]; - }; - - services.flatpak = { - enable = true; - packages = [ - ### Dev Tools ### - ### Internet Browsers & Communication ### - "app.zen_browser.zen" - ### Office & Productivity ### - ### Graphics & Design ### - "com.boxy_svg.BoxySVG" - ### Gaming & Entertainment ### - "com.github.k4zmu2a.spacecadetpinball" - "io.itch.itch" - "io.mrarm.mcpelauncher" - "org.freedesktop.Platform.VulkanLayer.MangoHud/x86_64/24.08" - ### System Utilities ### - "com.github.tchx84.Flatseal" - "io.github.Foldex.AdwSteamGtk" - "com.steamgriddb.SGDBoop" - ### Media ### - ]; - uninstallUnmanaged = true; - update.auto.enable = true; - }; - })) - ]; -} diff --git a/hosts/modules/rotterdam/default.nix b/hosts/modules/rotterdam/default.nix deleted file mode 100644 index 6671420..0000000 --- a/hosts/modules/rotterdam/default.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./ephermal.nix - ./hardware-configuration.nix - ./hardware.nix - ./programs.nix - ./services.nix - ]; -} diff --git a/hosts/modules/rotterdam/ephermal.nix b/hosts/modules/rotterdam/ephermal.nix deleted file mode 100644 index 8161a99..0000000 --- a/hosts/modules/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/modules/security.nix b/hosts/modules/security.nix deleted file mode 100644 index 5cb1786..0000000 --- a/hosts/modules/security.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ hostType, lib, ... }: - -{ - config = lib.mkMerge [ - # Common configuration - { - security = { - unprivilegedUsernsClone = true; # Needed for rootless podman - sudo = { - wheelNeedsPassword = false; - extraConfig = '' - Defaults lecture = never - ''; - }; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - }) - ]; -} diff --git a/hosts/modules/server/boot.nix b/hosts/modules/server/boot.nix new file mode 100644 index 0000000..5d6e482 --- /dev/null +++ b/hosts/modules/server/boot.nix @@ -0,0 +1,5 @@ +{ pkgs, ... }: + +{ + boot.kernelPackages = pkgs.linuxPackages_hardened; +} diff --git a/hosts/modules/server/nix.nix b/hosts/modules/server/nix.nix new file mode 100644 index 0000000..af57cae --- /dev/null +++ b/hosts/modules/server/nix.nix @@ -0,0 +1,13 @@ +{ inputs, ... }: + +{ + environment.etc."channels/nixpkgs".source = inputs.nixpkgs-stable.outPath; + + nix = { + registry.nixpkgs.flake = inputs.nixpkgs-stable; + nixPath = [ + "nixpkgs=/etc/channels/nixpkgs" + "/nix/var/nix/profiles/per-user/root/channels" + ]; + }; +} diff --git a/hosts/modules/server/tailscale.nix b/hosts/modules/server/tailscale.nix new file mode 100644 index 0000000..1f105ba --- /dev/null +++ b/hosts/modules/server/tailscale.nix @@ -0,0 +1,13 @@ +{ ... }: + +{ + services.tailscale = { + extraSetFlags = [ "--advertise-exit-node" ]; + useRoutingFeatures = "server"; + }; + + boot.kernel.sysctl = { + "net.ipv4.ip_forward" = 1; + "net.ipv6.conf.all.forwarding" = 1; + }; +} diff --git a/hosts/modules/services.nix b/hosts/modules/services.nix deleted file mode 100644 index b957a97..0000000 --- a/hosts/modules/services.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - services = { - fwupd.enable = true; - fstrim.enable = true; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - services = { - printing.enable = true; - udev.packages = with pkgs; [ yubikey-personalization ]; - keyd = { - enable = true; - keyboards.all = { - ids = [ "*" ]; - settings.main.capslock = "overload(meta, esc)"; - }; - }; - }; - }) - ]; -} diff --git a/hosts/modules/trantor/boot.nix b/hosts/modules/trantor/boot.nix deleted file mode 100644 index 35b8cb6..0000000 --- a/hosts/modules/trantor/boot.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ ... }: - -{ - boot = { - loader.efi.efiSysMountPoint = "/boot"; - initrd.systemd.enable = true; - kernel.sysctl."net.ipv4.ip_forward" = 1; - }; -} diff --git a/hosts/modules/trantor/default.nix b/hosts/modules/trantor/default.nix deleted file mode 100644 index 9bdb292..0000000 --- a/hosts/modules/trantor/default.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./disko.nix - ./hardware-configuration.nix - ./networking.nix - ]; -} diff --git a/hosts/modules/trantor/disko.nix b/hosts/modules/trantor/disko.nix deleted file mode 100644 index 39599f4..0000000 --- a/hosts/modules/trantor/disko.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ - disko.devices = { - disk = { - main = { - type = "disk"; - device = "/dev/sda"; - content = { - type = "gpt"; - partitions = { - boot = { - size = "512M"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - }; - }; - root = { - size = "100%"; - content = { - type = "filesystem"; - format = "ext4"; - mountpoint = "/"; - }; - }; - }; - }; - }; - }; - }; -} diff --git a/hosts/modules/trantor/hardware-configuration.nix b/hosts/modules/trantor/hardware-configuration.nix deleted file mode 100644 index d5cc31f..0000000 --- a/hosts/modules/trantor/hardware-configuration.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ - lib, - modulesPath, - ... -}: - -{ - imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; - - boot = { - kernelModules = [ ]; - extraModulePackages = [ ]; - initrd = { - availableKernelModules = [ - "xhci_pci" - "virtio_pci" - "virtio_scsi" - "usbhid" - ]; - kernelModules = [ ]; - }; - }; - - networking.useDHCP = lib.mkDefault true; - - nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; -} diff --git a/hosts/modules/users.nix b/hosts/modules/users.nix deleted file mode 100644 index e463781..0000000 --- a/hosts/modules/users.nix +++ /dev/null @@ -1,82 +0,0 @@ -{ - hostType, - inputs, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - users.users = { - user = { - isNormalUser = true; - shell = pkgs.fish; - extraGroups = [ - "networkmanager" - "docker" - "wheel" - ]; - openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL user@rotterdam" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3Y0PVpGfJHonqDS7qoCFhqzUvqGq9I9sax+F9e/5cs user@io" - ]; - hashedPassword = "$6$Pj7v/CpstyuWQQV0$cNujVDhfMBdwlGVEnnd8t71.kZPixbo0u25cd.874iaqLTH4V5fa1f98V5zGapjQCz5JyZmsR94xi00sUrntT0"; - }; - root = { - shell = pkgs.fish; - hashedPassword = "!"; - }; - }; - - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - backupFileExtension = "bkp"; - users = { - user = import ../../users/user.nix; - root = import ../../users/root.nix; - }; - extraSpecialArgs = { - inherit hostType; - inherit inputs; - }; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - 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 - }; - - users.users = { - user = { - description = "William"; - uid = 1000; - extraGroups = [ - "uaccess" # Needed for HID dev - "dialout" # Needed for arduino dev - "libvirt" - "libvirtd" - "adbusers" - "i2c" - ]; - }; - ewans = { - description = "Ewans"; - isNormalUser = true; - uid = 1001; - hashedPassword = "$y$j9T$yHLUDvj6bDIP19dchU.aA/$OY4qeFNtx/GvI.VUYx4LapHiiVwi0MEvs8AT0HN7j58"; - }; - }; - }) - ]; -} diff --git a/hosts/modules/virtualisation.nix b/hosts/modules/virtualisation.nix deleted file mode 100644 index 232459a..0000000 --- a/hosts/modules/virtualisation.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - virtualisation.podman = { - enable = true; - dockerCompat = true; - autoPrune.enable = true; - extraPackages = [ pkgs.podman-compose ]; - }; - - systemd = { - services.podman-auto-update.enable = true; - timers.podman-auto-update.enable = true; - }; - - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - virtualisation = { - libvirtd.enable = true; - lxd.enable = true; - }; - }) - ]; -} diff --git a/hosts/rotterdam.nix b/hosts/rotterdam.nix deleted file mode 100644 index ad95919..0000000 --- a/hosts/rotterdam.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ ... }: - -{ - networking.hostName = "rotterdam"; - - imports = [ - ./modules/rotterdam - ./modules - ]; - - nix.nixPath = [ "nixos-config=${./rotterdam.nix}" ]; -} diff --git a/hosts/modules/rotterdam/boot.nix b/hosts/rotterdam/boot.nix similarity index 80% rename from hosts/modules/rotterdam/boot.nix rename to hosts/rotterdam/boot.nix index 44dd48f..d038ede 100644 --- a/hosts/modules/rotterdam/boot.nix +++ b/hosts/rotterdam/boot.nix @@ -12,11 +12,7 @@ in 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" + "amdgpu.ppfeaturemask=0xfffd3fff" # Fixes amdgpu freezing ]; # QubesOS boot entry loader.systemd-boot = { diff --git a/hosts/modules/rotterdam/hardware-configuration.nix b/hosts/rotterdam/hardware-configuration.nix similarity index 100% rename from hosts/modules/rotterdam/hardware-configuration.nix rename to hosts/rotterdam/hardware-configuration.nix diff --git a/hosts/modules/rotterdam/hardware.nix b/hosts/rotterdam/hardware.nix similarity index 57% rename from hosts/modules/rotterdam/hardware.nix rename to hosts/rotterdam/hardware.nix index ba7f866..6f76e99 100644 --- a/hosts/modules/rotterdam/hardware.nix +++ b/hosts/rotterdam/hardware.nix @@ -2,10 +2,7 @@ { hardware = { - amdgpu = { - opencl.enable = true; - amdvlk.enable = true; - }; + amdgpu.opencl.enable = true; graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ]; }; } diff --git a/hosts/modules/rotterdam/programs.nix b/hosts/rotterdam/programs.nix similarity index 94% rename from hosts/modules/rotterdam/programs.nix rename to hosts/rotterdam/programs.nix index 9f624a1..b4dcfd9 100644 --- a/hosts/modules/rotterdam/programs.nix +++ b/hosts/rotterdam/programs.nix @@ -27,7 +27,5 @@ in { environment.systemPackages = [ reboot-into-qubes ]; - services.flatpak.packages = [ "net.retrodeck.retrodeck" ]; - programs.steam.dedicatedServer.openFirewall = true; } diff --git a/hosts/modules/rotterdam/services.nix b/hosts/rotterdam/services.nix similarity index 94% rename from hosts/modules/rotterdam/services.nix rename to hosts/rotterdam/services.nix index 5483b5d..0bf276f 100644 --- a/hosts/modules/rotterdam/services.nix +++ b/hosts/rotterdam/services.nix @@ -1,5 +1,3 @@ -{ ... }: - { services.keyd = { enable = true; diff --git a/hosts/trantor.nix b/hosts/trantor.nix deleted file mode 100644 index 4a02556..0000000 --- a/hosts/trantor.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ ... }: - -{ - networking.hostName = "trantor"; - - imports = [ - ./modules/trantor - ./modules - ]; - - nix.nixPath = [ "nixos-config=${./trantor.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/modules/trantor/networking.nix b/hosts/trantor/networking.nix similarity index 92% rename from hosts/modules/trantor/networking.nix rename to hosts/trantor/networking.nix index cb7b88a..4dcbe1e 100644 --- a/hosts/modules/trantor/networking.nix +++ b/hosts/trantor/networking.nix @@ -1,5 +1,3 @@ -{ ... }: - { networking = { firewall = { 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 4325e5f..0000000 --- a/packages/plasticity.nix +++ /dev/null @@ -1,122 +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, - libgbm, - nspr, - nss, - openssl, - pango, - rpmextract, - stdenv, - systemd, - trash-cli, - vulkan-loader, - wrapGAppsHook3, - xdg-utils, - xorg, -}: -stdenv.mkDerivation rec { - pname = "plasticity"; - version = "25.1.8"; - - src = fetchurl { - url = "https://github.com/nkallen/plasticity/releases/download/v${version}/Plasticity-${version}-1.x86_64.rpm"; - hash = "sha256-5PjjEsHchryUhmzqyQ4XqwiycNEVCefmpSW/9jZEzpg="; - }; - - nativeBuildInputs = [ - wrapGAppsHook3 - autoPatchelfHook - rpmextract - libgbm - ]; - - 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 - (lib.getLib stdenv.cc.cc) - 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 - rm -r $out/lib/.build-id - - runHook postInstall - ''; - - #--use-gl=egl for it to use hardware rendering it seems. Otherwise there are terrible framerates - preFixup = '' - gappsWrapperArgs+=(--add-flags "--use-gl=egl") - ''; -} diff --git a/readme.md b/readme.md index 9daeedb..a2b815f 100644 --- a/readme.md +++ b/readme.md @@ -1,8 +1,87 @@ -All my personal Nix and NixOS hosts, in a flake. +# Nix Configuration -|Host|Description|Nixpkgs version| -|:---|:---:|---:| -|alexandria|Personal server/NAS|25.05| -|io|Mobile workstation|unstable| -|rotterdam|Workstation|unstable| -|trantor|VPS in Oracle Cloud|25.05| +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/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/default.nix b/users/modules/default.nix deleted file mode 100644 index adc20f9..0000000 --- a/users/modules/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{...}: - -{ - imports = [ - ./programs.nix - ]; -} 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/programs.nix b/users/modules/programs.nix deleted file mode 100644 index 6558ea2..0000000 --- a/users/modules/programs.nix +++ /dev/null @@ -1,99 +0,0 @@ -{ - config, - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - home = { - sessionVariables = { - EDITOR = "hx"; - }; - }; - - programs = { - bash = { - enable = true; - }; - - helix = { - enable = true; - settings = { - theme = "catppuccin_mocha"; - 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"; - o = "file_picker_in_current_buffer_directory"; - esc = [ - "collapse_selection" - "keep_primary_selection" - ]; - }; - }; - }; - - fish = { - enable = true; - functions.fish_greeting = ""; - 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="; - }; - } - ]; - }; - }; - - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - }) - ]; -} diff --git a/users/modules/root/default.nix b/users/modules/root/default.nix deleted file mode 100644 index adc92a0..0000000 --- a/users/modules/root/default.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ ... }: - -{ - imports = [ ]; -} 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/users/modules/stylix.nix b/users/modules/stylix.nix new file mode 100644 index 0000000..f1c7e44 --- /dev/null +++ b/users/modules/stylix.nix @@ -0,0 +1,69 @@ +{ + config, + inputs, + pkgs, + ... +}: + +{ + imports = [ + inputs.stylix.homeModules.stylix + inputs.zen-browser.homeModules.beta + ]; + + stylix = { + enable = true; + polarity = "dark"; + base16Scheme = "${pkgs.base16-schemes}/share/themes/tokyodark.yaml"; + cursor = { + 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; + popups = config.stylix.opacity.desktop; + terminal = 1.0; + }; + fonts = { + serif = { + package = pkgs.source-serif; + name = "Source Serif 4 Display"; + }; + sansSerif = { + package = pkgs.inter; + name = "Inter"; + }; + monospace = { + package = pkgs.nerd-fonts.fira-code; + name = "FiraCode Nerd Font"; + }; + emoji = { + package = pkgs.noto-fonts-color-emoji; + name = "Noto Color Emoji"; + }; + sizes = { + applications = 10; + desktop = config.stylix.fonts.sizes.applications; + popups = config.stylix.fonts.sizes.applications; + 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/modules/user/default.nix b/users/modules/user/default.nix deleted file mode 100644 index 660553d..0000000 --- a/users/modules/user/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: - -{ - imports = [ - ./programs.nix - ./home.nix - ]; -} diff --git a/users/modules/user/home.nix b/users/modules/user/home.nix deleted file mode 100644 index 869d579..0000000 --- a/users/modules/user/home.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ pkgs, ... }: - -{ - home.pointerCursor = { - package = pkgs.kdePackages.breeze; - name = "Breeze_Light"; - gtk.enable = true; - x11.enable = true; - }; - - gtk = { - enable = true; - iconTheme = { - package = pkgs.morewaita-icon-theme; - name = "MoreWaita"; - }; - gtk3.extraConfig = { - gtk-decoration-layout = "appmenu:"; - }; - gtk4.extraConfig = { - gtk-decoration-layout = "appmenu:"; - }; - }; -} diff --git a/users/modules/user/programs.nix b/users/modules/user/programs.nix deleted file mode 100644 index 9b25dbb..0000000 --- a/users/modules/user/programs.nix +++ /dev/null @@ -1,141 +0,0 @@ -{ - config, - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - home = { - packages = with pkgs; [ nix-your-shell ]; - }; - - programs = { - helix.languages = { - language = [ - { - name = "nix"; - auto-format = true; - formatter.command = "nixfmt"; - } - { - name = "typst"; - auto-format = true; - formatter.command = "typstyle -c 1000 -i"; - } - ]; - }; - - password-store.enable = true; - - direnv = { - enable = true; - nix-direnv.enable = true; - }; - - fish = { - interactiveShellInit = "nix-your-shell fish | source"; - loginShellInit = "nix-your-shell fish | source"; - }; - - tmux = { - enable = true; - clock24 = true; - terminal = "xterm-256color"; - mouse = true; - keyMode = "vi"; - }; - - 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 = "󱄅 "; - }; - }; - }; - - 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; - }; - }; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - 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/root.nix b/users/root.nix deleted file mode 100644 index be5e00b..0000000 --- a/users/root.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ ... }: - -{ - home = { - username = "root"; - homeDirectory = "/root"; - stateVersion = "22.05"; - }; - - imports = [ - ./modules - ./modules/root - ]; -} diff --git a/users/user.nix b/users/user.nix deleted file mode 100644 index 9950533..0000000 --- a/users/user.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ ... }: - -{ - home = { - username = "user"; - homeDirectory = "/home/user"; - stateVersion = "22.05"; - }; - - imports = [ - ./modules - ./modules/user - ]; -} 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; + } + ]; +}