diff --git a/.gitignore b/.gitignore index 2a47a91..73105bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +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 4723329..27c3580 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1750173260, - "narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=", + "lastModified": 1761656077, + "narHash": "sha256-lsNWuj4Z+pE7s0bd2OKicOFq9bK86JE0ZGeKJbNqb94=", "owner": "ryantm", "repo": "agenix", - "rev": "531beac616433bac6f9e2a19feb8e99a22a66baf", + "rev": "9ba0d85de3eaa7afeab493fed622008b6e4924f5", "type": "github" }, "original": { @@ -28,11 +28,11 @@ "fromYaml": "fromYaml" }, "locked": { - "lastModified": 1746562888, - "narHash": "sha256-YgNJQyB5dQiwavdDFBMNKk1wyS77AtdgDk/VtU6wEaI=", + "lastModified": 1755819240, + "narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=", "owner": "SenchoPens", "repo": "base16.nix", - "rev": "806a1777a5db2a1ef9d5d6f493ef2381047f2b89", + "rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6", "type": "github" }, "original": { @@ -44,27 +44,28 @@ "base16-fish": { "flake": false, "locked": { - "lastModified": 1622559957, - "narHash": "sha256-PebymhVYbL8trDVVXxCvZgc0S5VxI7I1Hv4RMSquTpA=", + "lastModified": 1754405784, + "narHash": "sha256-l9xHIy+85FN+bEo6yquq2IjD1rSg9fjfjpyGP1W8YXo=", "owner": "tomyun", "repo": "base16-fish", - "rev": "2f6dd973a9075dabccd26f1cded09508180bf5fe", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", "type": "github" }, "original": { "owner": "tomyun", "repo": "base16-fish", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", "type": "github" } }, "base16-helix": { "flake": false, "locked": { - "lastModified": 1748408240, - "narHash": "sha256-9M2b1rMyMzJK0eusea0x3lyh3mu5nMeEDSc4RZkGm+g=", + "lastModified": 1752979451, + "narHash": "sha256-0CQM+FkYy0fOO/sMGhOoNL80ftsAzYCg9VhIrodqusM=", "owner": "tinted-theming", "repo": "base16-helix", - "rev": "6c711ab1a9db6f51e2f6887cc3345530b33e152e", + "rev": "27cf1e66e50abc622fb76a3019012dc07c678fac", "type": "github" }, "original": { @@ -90,6 +91,28 @@ "type": "github" } }, + "blueprint": { + "inputs": { + "nixpkgs": [ + "nix-ai-tools", + "nixpkgs" + ], + "systems": "systems_3" + }, + "locked": { + "lastModified": 1763308703, + "narHash": "sha256-O9Y+Wer8wOh+N+4kcCK5p/VLrXyX+ktk0/s3HdZvJzk=", + "owner": "numtide", + "repo": "blueprint", + "rev": "5a9bba070f801d63e2af3c9ef00b86b212429f4f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "blueprint", + "type": "github" + } + }, "darwin": { "inputs": { "nixpkgs": [ @@ -112,23 +135,40 @@ "type": "github" } }, - "disko": { + "deploy-rs": { "inputs": { - "nixpkgs": [ - "nixpkgs-stable" - ] + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "utils": "utils" }, "locked": { - "lastModified": 1736864502, - "narHash": "sha256-ItkIZyebGvNH2dK9jVGzJHGPtb6BSWLN8Gmef16NeY0=", + "lastModified": 1756719547, + "narHash": "sha256-N9gBKUmjwRKPxAafXEk1EGadfk2qDZPBQp4vXWPHINQ=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "125ae9e3ecf62fb2c0fd4f2d894eb971f1ecaed2", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "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" } @@ -136,11 +176,11 @@ "firefox-gnome-theme": { "flake": false, "locked": { - "lastModified": 1748383148, - "narHash": "sha256-pGvD/RGuuPf/4oogsfeRaeMm6ipUIznI2QSILKjKzeA=", + "lastModified": 1758112371, + "narHash": "sha256-lizRM2pj6PHrR25yimjyFn04OS4wcdbc38DCdBVa2rk=", "owner": "rafaelmardojai", "repo": "firefox-gnome-theme", - "rev": "4eb2714fbed2b80e234312611a947d6cb7d70caf", + "rev": "0909cfe4a2af8d358ad13b20246a350e14c2473d", "type": "github" }, "original": { @@ -152,11 +192,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1747046372, - "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", "type": "github" }, "original": { @@ -166,12 +206,13 @@ } }, "flake-compat_2": { + "flake": false, "locked": { - "lastModified": 1747046372, - "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "lastModified": 1761588595, + "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", "owner": "edolstra", "repo": "flake-compat", - "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "type": "github" }, "original": { @@ -181,6 +222,24 @@ } }, "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", @@ -188,11 +247,32 @@ ] }, "locked": { - "lastModified": 1743550720, - "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "lastModified": 1756770412, + "narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "c621e8422220273271f52058f618c94e405bb0f5", + "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": { @@ -203,7 +283,25 @@ }, "flake-utils": { "inputs": { - "systems": "systems_2" + "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, @@ -235,54 +333,6 @@ "type": "github" } }, - "git-hooks": { - "inputs": { - "flake-compat": [ - "stylix", - "flake-compat" - ], - "gitignore": "gitignore", - "nixpkgs": [ - "stylix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1747372754, - "narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "stylix", - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "gnome-shell": { "flake": false, "locked": { @@ -321,27 +371,6 @@ "type": "github" } }, - "home-manager-stable": { - "inputs": { - "nixpkgs": [ - "nixpkgs-stable" - ] - }, - "locked": { - "lastModified": 1751468302, - "narHash": "sha256-tWosziZTT039x6PgEZUhzGlV8oLvdDmIgKTE8ESMaEA=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "501cfec8277f931a9c9af9f23d3105c537faeafe", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "release-25.05", - "repo": "home-manager", - "type": "github" - } - }, "home-manager_2": { "inputs": { "nixpkgs": [ @@ -349,11 +378,11 @@ ] }, "locked": { - "lastModified": 1751476662, - "narHash": "sha256-eX6wMGQjaTzedR6lz2IpEnAMgLcuQLQezBJNil7yG3s=", + "lastModified": 1762178366, + "narHash": "sha256-I+8yE5HVR2SFcHnW0771psQ/zn0qVzsKHY/gUM0nEVM=", "owner": "nix-community", "repo": "home-manager", - "rev": "9347c61bc0cbed0d2062b930144c2cbd557f9189", + "rev": "8c824254b1ed9e797f6235fc3c62f365893c561a", "type": "github" }, "original": { @@ -366,16 +395,16 @@ "home-manager_3": { "inputs": { "nixpkgs": [ - "stylix", + "zen-browser", "nixpkgs" ] }, "locked": { - "lastModified": 1751146119, - "narHash": "sha256-gvjG95TCnUVJkvQvLMlnC4NqiqFyBdJk3o8/RwuHeaU=", + "lastModified": 1752603129, + "narHash": "sha256-S+wmHhwNQ5Ru689L2Gu8n1OD6s9eU9n9mD827JNR+kw=", "owner": "nix-community", "repo": "home-manager", - "rev": "76d0c31fce2aa0c71409de953e2f9113acd5b656", + "rev": "e8c19a3cec2814c754f031ab3ae7316b64da085b", "type": "github" }, "original": { @@ -399,13 +428,109 @@ "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": 1751276396, - "narHash": "sha256-oOYrnKStMsOXST+wKnzuSZ49h8Dr1Q3mIn2f5Kb5GAw=", + "lastModified": 1754777568, + "narHash": "sha256-0bBqT+3XncgF8F03RFAamw9vdf0VmaDoIJLTGkjfQZs=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "59adb9ad1cbd915494fc35cd0e0a9d582ca9de74", + "rev": "62f636b87ef6050760a8cb325cadb90674d1e23e", "type": "github" }, "original": { @@ -415,11 +540,31 @@ "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", - "rust-overlay": "rust-overlay" + "nixpkgs": "nixpkgs_6", + "rust-overlay": "rust-overlay_2" }, "locked": { "lastModified": 1742115705, @@ -438,16 +583,16 @@ }, "nixos-cli": { "inputs": { - "flake-compat": "flake-compat", + "flake-compat": "flake-compat_2", "nix-options-doc": "nix-options-doc", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_7" }, "locked": { - "lastModified": 1752359519, - "narHash": "sha256-ksd2Gu1JpKU3rKvbkpiUlrkY72M8VAln1w4W7pj77WQ=", + "lastModified": 1761970410, + "narHash": "sha256-IUm2nkbKlDkG94ruTmIYLERpBn6gXydm3scZIKzpcKs=", "owner": "nix-community", "repo": "nixos-cli", - "rev": "c2778572d75bc27ae2234653c5ce9489930d0c7d", + "rev": "5c259f72ae1eaa00b99354d81130d8fddb7f9a7a", "type": "github" }, "original": { @@ -457,6 +602,165 @@ } }, "nixpkgs": { + "locked": { + "lastModified": 1743014863, + "narHash": "sha256-jAIUqsiN2r3hCuHji80U7NNEafpIMBXiwKlSrjWMlpg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bd3bac8bfb542dbde7ffffb6987a1a1f9d41699f", + "type": "github" + }, + "original": { + "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": 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": "3de8f8d73e35724bf9abef41f1bdbedda1e14a31", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1762111121, + "narHash": "sha256-4vhDuZ7OZaZmKKrnDpxLZZpGIJvAeMtK6FKLJYUtAdw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b3d51a0365f6695e7dd5cdf3e180604530ed33b4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 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=", @@ -472,29 +776,13 @@ "type": "github" } }, - "nixpkgs-stable": { + "nixpkgs_7": { "locked": { - "lastModified": 1751211869, - "narHash": "sha256-1Cu92i1KSPbhPCKxoiVG5qnoRiKTgR5CcGSRyLpOd7Y=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "b43c397f6c213918d6cfe6e3550abfe79b5d1c51", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-25.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1751625545, - "narHash": "sha256-4E7wWftF1ExK5ZEDzj41+9mVgxtuRV3wWCId7QAYMAU=", + "lastModified": 1761880412, + "narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c860cf0b3a0829f0f6cf344ca8de83a2bbfab428", + "rev": "a7fc11be66bdfb5cdde611ee5ce381c183da8386", "type": "github" }, "original": { @@ -504,13 +792,13 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_8": { "locked": { - "lastModified": 1751271578, - "narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", + "lastModified": 1761907660, + "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", "owner": "nixos", "repo": "nixpkgs", - "rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", + "rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15", "type": "github" }, "original": { @@ -520,6 +808,44 @@ "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": [ @@ -529,15 +855,14 @@ "nixpkgs": [ "stylix", "nixpkgs" - ], - "treefmt-nix": "treefmt-nix" + ] }, "locked": { - "lastModified": 1748730660, - "narHash": "sha256-5LKmRYKdPuhm8j5GFe3AfrJL8dd8o57BQ34AGjJl1R0=", + "lastModified": 1758998580, + "narHash": "sha256-VLx0z396gDCGSiowLMFz5XRO/XuNV+4EnDYjdJhHvUk=", "owner": "nix-community", "repo": "NUR", - "rev": "2c0bc52fe14681e9ef60e3553888c4f086e46ecb", + "rev": "ba8d9c98f5f4630bcb0e815ab456afd90c930728", "type": "github" }, "original": { @@ -546,21 +871,72 @@ "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", + "nix-index-database": "nix-index-database", "nixos-cli": "nixos-cli", - "nixpkgs": "nixpkgs_3", - "nixpkgs-stable": "nixpkgs-stable", - "stylix": "stylix" + "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", @@ -589,16 +965,11 @@ "base16-helix": "base16-helix", "base16-vim": "base16-vim", "firefox-gnome-theme": "firefox-gnome-theme", - "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts", - "git-hooks": "git-hooks", + "flake-parts": "flake-parts_2", "gnome-shell": "gnome-shell", - "home-manager": "home-manager_3", - "nixpkgs": [ - "nixpkgs" - ], + "nixpkgs": "nixpkgs_9", "nur": "nur", - "systems": "systems_3", + "systems": "systems_6", "tinted-foot": "tinted-foot", "tinted-kitty": "tinted-kitty", "tinted-schemes": "tinted-schemes", @@ -606,11 +977,11 @@ "tinted-zed": "tinted-zed" }, "locked": { - "lastModified": 1751478235, - "narHash": "sha256-fzU40SfJxDQlsWabd7ApiGiJHJVLe+vjCm8JtJU9mwc=", + "lastModified": 1762101397, + "narHash": "sha256-wGiL2K3kAyBBmIZpJEskaSIgyzzpg0zwfvri+Sy6/CI=", "owner": "danth", "repo": "stylix", - "rev": "3f71d154867b457adbef04b4982e78b5dc225e62", + "rev": "8c0640d5722a02178c8ee80a62c5f019cab4b3c1", "type": "github" }, "original": { @@ -664,6 +1035,103 @@ "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": { @@ -700,11 +1168,11 @@ "tinted-schemes": { "flake": false, "locked": { - "lastModified": 1748180480, - "narHash": "sha256-7n0XiZiEHl2zRhDwZd/g+p38xwEoWtT0/aESwTMXWG4=", + "lastModified": 1757716333, + "narHash": "sha256-d4km8W7w2zCUEmPAPUoLk1NlYrGODuVa3P7St+UrqkM=", "owner": "tinted-theming", "repo": "schemes", - "rev": "87d652edd26f5c0c99deda5ae13dfb8ece2ffe31", + "rev": "317a5e10c35825a6c905d912e480dfe8e71c7559", "type": "github" }, "original": { @@ -716,11 +1184,11 @@ "tinted-tmux": { "flake": false, "locked": { - "lastModified": 1748740859, - "narHash": "sha256-OEM12bg7F4N5WjZOcV7FHJbqRI6jtCqL6u8FtPrlZz4=", + "lastModified": 1757811970, + "narHash": "sha256-n5ZJgmzGZXOD9pZdAl1OnBu3PIqD+X3vEBUGbTi4JiI=", "owner": "tinted-theming", "repo": "tinted-tmux", - "rev": "57d5f9683ff9a3b590643beeaf0364da819aedda", + "rev": "d217ba31c846006e9e0ae70775b0ee0f00aa6b1e", "type": "github" }, "original": { @@ -732,11 +1200,11 @@ "tinted-zed": { "flake": false, "locked": { - "lastModified": 1725758778, - "narHash": "sha256-8P1b6mJWyYcu36WRlSVbuj575QWIFZALZMTg5ID/sM4=", + "lastModified": 1757811247, + "narHash": "sha256-4EFOUyLj85NRL3OacHoLGEo0wjiRJzfsXtR4CZWAn6w=", "owner": "tinted-theming", "repo": "base16-zed", - "rev": "122c9e5c0e6f27211361a04fae92df97940eccf9", + "rev": "824fe0aacf82b3c26690d14e8d2cedd56e18404e", "type": "github" }, "original": { @@ -748,17 +1216,16 @@ "treefmt-nix": { "inputs": { "nixpkgs": [ - "stylix", - "nur", + "nix-ai-tools", "nixpkgs" ] }, "locked": { - "lastModified": 1733222881, - "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", + "lastModified": 1762938485, + "narHash": "sha256-AlEObg0syDl+Spi4LsZIBrjw+snSVU4T8MOeuZJUJjM=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "49717b5af6f80172275d47a418c9719a31a78b53", + "rev": "5b4ee75aeefd1e2d5a1cc43cf6ba65eba75e83e4", "type": "github" }, "original": { @@ -766,6 +1233,95 @@ "repo": "treefmt-nix", "type": "github" } + }, + "utils": { + "inputs": { + "systems": "systems_2" + }, + "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" + } + }, + "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 9b13d69..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,179 +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"; - }; - - stylix = { - url = "github:danth/stylix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; agenix = { url = "github:ryantm/agenix"; inputs.nixpkgs.follows = "nixpkgs-stable"; }; - disko = { - url = "github:nix-community/disko?ref=v1.11.0"; - inputs.nixpkgs.follows = "nixpkgs-stable"; + disko.url = "github:nix-community/disko"; + + noctalia = { + url = "github:noctalia-dev/noctalia-shell"; + inputs.nixpkgs.follows = "nixpkgs"; }; + stylix.url = "github:danth/stylix"; + nixos-cli.url = "github:nix-community/nixos-cli"; nix-flatpak.url = "github:gmodena/nix-flatpak/main"; + zen-browser.url = "github:0xc000022070/zen-browser-flake"; + impermanence.url = "github:nix-community/impermanence"; + + deploy-rs.url = "github:serokell/deploy-rs"; + + niri-flake.url = "github:sodiboo/niri-flake"; + + niri.url = "github:baduhai/niri/auto-center-when-space-available"; + + nix-index-database = { + url = "github:nix-community/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + terranix = { + url = "github:terranix/terranix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + nix-ai-tools.url = "github:numtide/nix-ai-tools"; + + vicinae.url = "github:vicinaehq/vicinae"; }; outputs = - inputs@{ - self, - nixpkgs, - nixpkgs-stable, - home-manager, - home-manager-stable, - stylix, - disko, - agenix, - nixos-cli, - nix-flatpak, - impermanence, - ... - }: - let + inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { systems = [ "x86_64-linux" "aarch64-linux" ]; - forAllSystems = nixpkgs.lib.genAttrs systems; - forAllSystemsWithPkgs = - f: - forAllSystems ( - system: - let - pkgs = nixpkgs.legacyPackages.${system}; - in - f system pkgs - ); - in - { - 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 - stylix.nixosModules.stylix - nixos-cli.nixosModules.nixos-cli - { - 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"; - }; - }; - devShells = forAllSystemsWithPkgs ( - system: pkgs: { - default = pkgs.mkShell { - packages = with pkgs; [ - nil - nixfmt-rfc-style - ]; - }; - } - ); - - packages = forAllSystemsWithPkgs ( - system: pkgs: - { - toggleaudiosink = pkgs.callPackage ./packages/toggleaudiosink.nix { }; - } - // nixpkgs.lib.optionalAttrs (system == "x86_64-linux") { - plasticity = pkgs.callPackage ./packages/plasticity.nix { }; - } - ); - - overlays = { - overlay = final: prev: { - }; - workstationOverlay = final: prev: { - plasticity = self.packages.${final.system}.plasticity; - toggleaudiosink = self.packages.${final.system}.toggleaudiosink; - }; - serverOverlay = final: prev: { - }; - }; - - 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/alexandria/nextcloud.nix b/hosts/alexandria/nextcloud.nix new file mode 100644 index 0000000..c449cce --- /dev/null +++ b/hosts/alexandria/nextcloud.nix @@ -0,0 +1,97 @@ +{ + lib, + config, + pkgs, + inputs, + ... +}: + +let + utils = import ../../utils.nix { inherit inputs lib; }; + inherit (utils) mkNginxVHosts; +in + +{ + services = { + nextcloud = { + enable = true; + package = pkgs.nextcloud32; + datadir = "/data/nextcloud"; + hostName = "cloud.baduhai.dev"; + configureRedis = true; + https = 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; + }; + settings = { + 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" + "OC\\Preview\\Font" + "OC\\Preview\\GIF" + "OC\\Preview\\HEIC" + "OC\\Preview\\Illustrator" + "OC\\Preview\\JPEG" + "OC\\Preview\\Krita" + "OC\\Preview\\MarkDown" + "OC\\Preview\\Movie" + "OC\\Preview\\MP3" + "OC\\Preview\\MSOffice2003" + "OC\\Preview\\MSOffice2007" + "OC\\Preview\\MSOfficeDoc" + "OC\\Preview\\OpenDocument" + "OC\\Preview\\PDF" + "OC\\Preview\\Photoshop" + "OC\\Preview\\PNG" + "OC\\Preview\\Postscript" + "OC\\Preview\\SVG" + "OC\\Preview\\TIFF" + "OC\\Preview\\TXT" + "OC\\Preview\\XBitmap" + ]; + }; + config = { + dbtype = "pgsql"; + adminpassFile = config.age.secrets.nextcloud-adminpass.path; + }; + phpOptions = { + "opcache.interned_strings_buffer" = "16"; + }; + }; + + nginx.virtualHosts = mkNginxVHosts { + domains."cloud.baduhai.dev" = { }; + }; + }; + + age.secrets = { + "nextcloud-secrets.json" = { + file = ../../secrets/nextcloud-secrets.json.age; + owner = "nextcloud"; + group = "nextcloud"; + }; + nextcloud-adminpass = { + file = ../../secrets/nextcloud-adminpass.age; + owner = "nextcloud"; + 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 100% rename from hosts/modules/io/boot.nix rename to hosts/io/boot.nix 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/modules/io/hardware-configuration.nix b/hosts/io/hardware-configuration.nix similarity index 98% rename from hosts/modules/io/hardware-configuration.nix rename to hosts/io/hardware-configuration.nix index 56f0d0d..8e4dae4 100644 --- a/hosts/modules/io/hardware-configuration.nix +++ b/hosts/io/hardware-configuration.nix @@ -2,6 +2,7 @@ config, lib, modulesPath, + inputs, ... }: 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 f9f82cf..df41a6f 100644 --- a/hosts/modules/io/services.nix +++ b/hosts/io/services.nix @@ -1,3 +1,5 @@ +{ pkgs, ... }: + { services = { keyd = { @@ -46,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/default.nix b/hosts/modules/alexandria/default.nix deleted file mode 100644 index 40a4da2..0000000 --- a/hosts/modules/alexandria/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ ... }: - -{ - imports = [ - ./hardware-configuration.nix - ./services.nix - ./users.nix - ]; -} diff --git a/hosts/modules/alexandria/networking.nix b/hosts/modules/alexandria/networking.nix deleted file mode 100644 index 2d59cbb..0000000 --- a/hosts/modules/alexandria/networking.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - networking = { - firewall = { - allowedTCPPorts = [ - 80 - 443 - ]; - allowedUDPPorts = [ ]; - }; - }; - - boot.kernel.sysctl = { - "net.ipv4.ip_forward" = 1; - "net.ipv6.conf.all.forwarding" = 1; - }; -} diff --git a/hosts/modules/alexandria/services.nix b/hosts/modules/alexandria/services.nix deleted file mode 100644 index 7de15d5..0000000 --- a/hosts/modules/alexandria/services.nix +++ /dev/null @@ -1,225 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - ports = { - jellyfin = "8096"; - librespeed = "8000"; - radicale = "8001"; - vaultwarden = "8002"; - }; - rclone-webdav-start = pkgs.writeShellScript "rclone-webdav-start.sh" '' - #!/bin/bash - - # Configuration - CREDS_FILE="/run/agenix/webdav" - SERVE_DIR="/data/webdav" - SOCKET_PATH="/run/rclone-webdav/webdav.sock" - - # Check if credentials file exists - if [ ! -f "$CREDS_FILE" ]; then - echo "Error: Credentials file $CREDS_FILE not found" - exit 1 - fi - - # Read credentials from file (format: username:password) - CREDENTIALS=$(cat "$CREDS_FILE") - USERNAME=$(echo "$CREDENTIALS" | cut -d':' -f1) - PASSWORD=$(echo "$CREDENTIALS" | cut -d':' -f2) - - # Validate credentials - if [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then - echo "Error: Invalid credentials format. Expected username:password" - exit 1 - fi - - # Ensure serve directory exists - mkdir -p "$SERVE_DIR" - - # Remove existing socket if it exists - rm -f "$SOCKET_PATH" - - # Start rclone serve webdav - exec ${pkgs.rclone}/bin/rclone serve webdav "$SERVE_DIR" \ - --addr unix://"$SOCKET_PATH" \ - --user "$USERNAME" \ - --pass "$PASSWORD" \ - --config="" \ - --baseurl "/webdav" \ - --verbose - ''; -in - -{ - services = { - forgejo = { - enable = true; - repositoryRoot = "/data/forgejo"; - 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 = "baduhai.dev"; - }; - log.LEVEL = "Warn"; - mailer.ENABLED = false; - actions.ENABLED = false; - }; - }; - - jellyfin = { - enable = true; - openFirewall = true; - }; - - nginx = { - enable = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - virtualHosts = - let - commonVHostConfig = { - useACMEHost = "baduhai.dev"; - forceSSL = true; - kTLS = true; - }; - in - lib.mapAttrs (_: lib.recursiveUpdate commonVHostConfig) { - "_".locations."/".return = "444"; - "dav.baduhai.dev".locations = { - "/caldav" = { - proxyPass = "http://127.0.0.1:${ports.radicale}/"; - extraConfig = '' - proxy_set_header X-Script-Name /caldav; - proxy_pass_header Authorization; - ''; - }; - "/webdav" = { - proxyPass = "http://unix:/run/rclone-webdav/webdav.sock:/webdav/"; - extraConfig = '' - proxy_set_header X-Script-Name /webdav; - proxy_pass_header Authorization; - proxy_connect_timeout 300; # Increase timeouts for large file uploads - proxy_send_timeout 300; - proxy_read_timeout 300; - client_max_body_size 10G; # Allow large file uploads - proxy_buffering off; # Buffer settings for better performance - proxy_request_buffering off; - ''; - }; - }; - "git.baduhai.dev".locations."/".proxyPass = - "http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/"; - "jellyfin.baduhai.dev".locations."/".proxyPass = "http://127.0.0.1:${ports.jellyfin}/"; - "pass.baduhai.dev".locations."/".proxyPass = "http://127.0.0.1:${ports.vaultwarden}/"; - "speedtest.baduhai.dev".locations."/".proxyPass = "http://127.0.0.1:${ports.librespeed}/"; - }; - }; - - radicale = { - enable = true; - settings = { - server = { - hosts = [ - "127.0.0.1:${ports.radicale}" - "[::]:${ports.radicale}" - ]; - }; - auth = { - type = "htpasswd"; - htpasswd_filename = "/etc/radicale/users"; - htpasswd_encryption = "bcrypt"; - }; - }; - }; - - vaultwarden = { - enable = true; - config = { - DOMAIN = "https://pass.baduhai.dev"; - SIGNUPS_ALLOWED = false; - ROCKET_ADDRESS = "127.0.0.1"; - ROCKET_PORT = "${ports.vaultwarden}"; - }; - }; - }; - - virtualisation.oci-containers.containers."librespeed" = { - image = "lscr.io/linuxserver/librespeed:latest"; - environment = { - TZ = "America/Bahia"; - }; - ports = [ "${ports.librespeed}:80" ]; - extraOptions = [ - "--pull=newer" - "--label=io.containers.autoupdate=registry" - ]; - }; - - 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" ]; - }; - }; - - age.secrets = { - cloudflare = { - file = ../../../secrets/cloudflare.age; - owner = "nginx"; - group = "nginx"; - }; - webdav = { - file = ../../../secrets/webdav.age; - owner = "user"; - group = "users"; - }; - }; - - systemd.services = { - rclone-webdav = { - description = "RClone WebDAV Server"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "exec"; - User = "user"; - Group = "nginx"; - ExecStart = "${rclone-webdav-start}"; - Restart = "always"; - RestartSec = "10"; - NoNewPrivileges = true; - PrivateTmp = true; - ProtectSystem = "strict"; - ProtectHome = true; - ReadWritePaths = [ - "/data/webdav" - "/run" - ]; - RuntimeDirectory = "rclone-webdav"; - RuntimeDirectoryMode = "0750"; - UMask = "0002"; - }; - preStart = '' - mkdir -p /data/webdav - chown user:users /data/webdav - chmod 755 /data/webdav - ''; - }; - }; -} diff --git a/hosts/modules/alexandria/users.nix b/hosts/modules/alexandria/users.nix deleted file mode 100644 index 14e34c2..0000000 --- a/hosts/modules/alexandria/users.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - users.users.nginx.extraGroups = [ "acme" ]; -} 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 049fad7..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; - 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 64c4aef..0000000 --- a/hosts/modules/default.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./console.nix - ./desktop.nix - ./ephermal.nix - ./impermanence.nix - ./locale.nix - ./networking.nix - ./nix.nix - ./programs.nix - ./security.nix - ./services.nix - ./stylix.nix - ./users.nix - ./virtualisation.nix - ]; -} diff --git a/hosts/modules/desktop.nix b/hosts/modules/desktop.nix deleted file mode 100644 index 6002f3e..0000000 --- a/hosts/modules/desktop.nix +++ /dev/null @@ -1,66 +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 = { - displayManager = { - autoLogin = { - enable = true; - user = "user"; - }; - sddm = { - enable = true; - wayland = { - enable = true; - compositor = "kwin"; - }; - }; - }; - desktopManager.plasma6.enable = true; - pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - jack.enable = true; - wireplumber.enable = true; - }; - }; - - 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; [ - kdePackages.xdg-desktop-portal-kde - 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/ephermal.nix b/hosts/modules/ephermal.nix deleted file mode 100644 index ff22557..0000000 --- a/hosts/modules/ephermal.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ - hostType, - lib, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - 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/mapper/cryptroot /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/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 b2182a6..0000000 --- a/hosts/modules/impermanence.nix +++ /dev/null @@ -1,42 +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" - "/etc/nixos" - "/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 fb244cc..0000000 --- a/hosts/modules/io/default.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./disko.nix - ./hardware-configuration.nix - ./programs.nix - ./services.nix - ]; -} diff --git a/hosts/modules/io/disko.nix b/hosts/modules/io/disko.nix deleted file mode 100644 index 3dc3b31..0000000 --- a/hosts/modules/io/disko.nix +++ /dev/null @@ -1,81 +0,0 @@ -{ ... }: - -{ - 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/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 d80f42e..0000000 --- a/hosts/modules/networking.nix +++ /dev/null @@ -1,29 +0,0 @@ -{ - hostType, - lib, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - networking = { - networkmanager.enable = true; - firewall.enable = true; - }; - } - - # 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 b79042d..0000000 --- a/hosts/modules/programs.nix +++ /dev/null @@ -1,209 +0,0 @@ -{ - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - environment = { - systemPackages = with pkgs; [ - ### Dev Tools ### - agenix - git - helix - ### System Utilities ### - btop - nixos-firewall-tool - nvd - sysz - tmux - wget - ]; - shellAliases = { - ls = "${pkgs.eza}/bin/eza --icons --group-directories-first"; - neofetch = "${pkgs.fastfetch}/bin/fastfetch"; - tree = "ls --tree"; - syscleanup = "sudo nix-collect-garbage -d; sudo /run/current-system/bin/switch-to-configuration boot"; - vi = "${pkgs.evil-helix}/bin/hx"; - vim = "${pkgs.evil-helix}/bin/hx"; - nvim = "${pkgs.evil-helix}/bin/hx"; - }; - }; - - programs = { - fish.enable = true; - command-not-found.enable = false; - }; - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation ( - let - kdepkgs = with pkgs.kdePackages; [ - ark - dolphin-plugins - kolourpaint - ]; - kwrite = pkgs.symlinkJoin { - name = "kwrite"; - paths = [ pkgs.kdePackages.kate ]; - postBuild = '' - rm -rf $out/bin/kate \ - $out/bin/.kate-wrapped \ - $out/share/applications/org.kde.kate.desktop \ - $out/share/man \ - $out/share/icons/hicolor/*/apps/kate.png \ - $out/share/icons/hicolor/scalable/apps/kate.svg \ - $out/share/appdata/org.kde.kate.appdata.xml - ''; - }; - in - { - environment = { - systemPackages = - with pkgs; - [ - ### Dev Tools ### - bat - ciscoPacketTracer8 - claude-code - 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 - kwrite - libreoffice-qt - obsidian - onlyoffice-desktopeditors - rnote - ### Graphics & Design ### - gimp - inkscape - plasticity - ### Gaming & Entertainment ### - clonehero - heroic - mangohud - prismlauncher - protonup - ### System Utilities ### - adwaita-icon-theme - junction - kara - kde-rounded-corners - libfido2 - mission-center - p7zip - qbittorrent - quickemu - quickgui - rclone - steam-run - toggleaudiosink - unrar - ### Media ### - mpv - obs-studio - qview - ] - ++ kdepkgs; - plasma6.excludePackages = with pkgs.kdePackages; [ - discover - elisa - gwenview - kate - khelpcenter - konsole - oxygen - ]; - }; - - 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" - 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; - }}"; - } - ### 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" - "com.rustdesk.RustDesk" - "com.steamgriddb.SGDBoop" - "io.github.Foldex.AdwSteamGtk" - ### 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 0bc2cc8..0000000 --- a/hosts/modules/rotterdam/default.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ ... }: - -{ - imports = [ - ./boot.nix - ./hardware-configuration.nix - ./hardware.nix - ./programs.nix - ./services.nix - ]; -} 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 351e091..0000000 --- a/hosts/modules/services.nix +++ /dev/null @@ -1,52 +0,0 @@ -{ - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - services = { - tailscale = { - enable = true; - extraUpFlags = [ "--operator=user" ]; - }; - openssh = { - enable = true; - settings.PermitRootLogin = "no"; - }; - nixos-cli = { - enable = true; - config = { - use_nvd = true; - ignore_dirty_tree = true; - }; - }; - 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/stylix.nix b/hosts/modules/stylix.nix deleted file mode 100644 index b0345f2..0000000 --- a/hosts/modules/stylix.nix +++ /dev/null @@ -1,63 +0,0 @@ -{ - config, - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - stylix = { - enable = true; - polarity = "dark"; - base16Scheme = "${pkgs.base16-schemes}/share/themes/catppuccin-mocha.yaml"; - cursor = { - package = pkgs.kdePackages.breeze-icons; - name = "Breeze_Light"; - size = 24; - }; - 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-emoji; - name = "Noto Color Emoji"; - }; - sizes = { - applications = 11; - desktop = config.stylix.fonts.sizes.applications; - popups = config.stylix.fonts.sizes.applications; - terminal = 12; - }; - }; - }; - }) - ]; -} diff --git a/hosts/modules/trantor/boot.nix b/hosts/modules/trantor/boot.nix deleted file mode 100644 index b724550..0000000 --- a/hosts/modules/trantor/boot.nix +++ /dev/null @@ -1,7 +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 a535e47..0000000 --- a/hosts/modules/trantor/disko.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ ... }: - -{ - disko.devices = { - disk = { - main = { - type = "disk"; - device = "/dev/disk/by-id/scsi-3605e4addb4c640319c8c03436205530b"; - 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 100% rename from hosts/modules/rotterdam/boot.nix rename to hosts/rotterdam/boot.nix 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 100% rename from hosts/modules/rotterdam/services.nix rename to hosts/rotterdam/services.nix 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 100% rename from hosts/modules/trantor/networking.nix rename to hosts/trantor/networking.nix 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 a496c54..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 = { - inherit 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 9f3af1e..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|System Version| -|:---|:---:|---:| -|alexandria|Personal server/NAS|NixOS 25.05| -|io|Mobile workstation|NixOS Unstable| -|rotterdam|Workstation|NixOS Unstable| -|trantor|Oracle Cloud VPS|NixOS 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 11cfac6..028e964 100644 --- a/secrets/cloudflare.age +++ b/secrets/cloudflare.age @@ -1,15 +1,11 @@ age-encryption.org/v1 --> ssh-ed25519 Kfdnog HMpl/3mb59SsUvkDXXxO+odBNSc1dZS1nQtC8/BPlGI -4fPk0YtGxOoqXDfTN9kQlH0Pg2iaJXUZE5es6f317L4 --> ssh-ed25519 SP9f6A p1kh6UOFJ4xwulLY9IpbNZIJ7JSouR27j6HgK/XRegM -rJCzN+RCdQgo/xCkAmcdN6GfXsoQhpmE1HuGwYs/2CI --> ssh-ed25519 8YSAiw cCbMOE3PMa3bzGGQSeQZuq074iwt4p4HLDu8uiHhWRY -U6wR/DuBdMKfbmQfUZ8XLdTBxNsUMR2lOueYucR5+bY --> ssh-ed25519 7cojTQ iLDzC79YtZcrqldzCyIFHrpsEapOXYD5AXuNoQ+3ulI -v2NiE3pA+J8Po+PqTTUU9XYKy37AIyj5KWdlh7FOPG8 --> ssh-ed25519 J6tVTA Jw1pSpF1J2Ud46BDhdRCPErgUeim8uwWxiB1E3BiJB8 -hGdGFi46iqKJN0QviG1xRNf2kwlls0rM5k3LkAiw8jY --> ssh-ed25519 Kl5yTQ yXnKCsJNjTSQYiPuv6dAF6raB3EFcg2oag1cBVkdvwk -0hwjrZpclTrFWtr5JqAbwXImYzZwTJOJPkhNnlHmPeo ---- k97ZU6FfTWVqBwNcrF9QeEbnqnuQUQ9pR1qM/Sgjh7A -#L-q﹋hr&*hNbqܦHŠG=@uaku|Er^BOo}:5ju$%".A1qP\2C R_ S=(%sި \ No newline at end of file +-> ssh-ed25519 Kfdnog IHXv4c5we36dCUsB1v8uEF23tIRlDQ/8WR1hX4GQ+Uc +Cwccw64BYBdSZUdkSqKESIU7E17cLNtiAZZ3Y1xV87A +-> ssh-ed25519 8YSAiw Ce3vdMG111ubjcFgd3+q2Qw2+7dsoUz7SiudtuLDr0Y +JUodwFsKfOTZXxFyRrEk/4gxJ4goPkwvYeThi893M0U +-> ssh-ed25519 J6tVTA bExFuITTGXkTvhW25nushN7zT/PJGDoezsqu7fLKemI +4a90v0F4wgcZeqWBQ/EpqOZ9OCgT7qruwVvlGZeFmN8 +-> ssh-ed25519 Qt3Q+A j1oo46pNh1+yPEtxpgj+QPQPf5m82jL0DHGMacY8UFA +vy52Hl1WLTdKNA8+4p7A48Sg9+QkMXbECf/uxVMCLYk +--- 429vzgFnmFbEqDMwdvC0/EYDJlKU64YEGgE0AqPqlBs +b/!8O3Df/&kNQhurt%&]ucjH]_5@D$>N8Ϧ >9:CvѦ69W'X]X^ƻ$}|c/ ߸={uɳs \ No newline at end of file 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 new file mode 100644 index 0000000..b4a29fa Binary files /dev/null and b/secrets/nextcloud-adminpass.age differ diff --git a/secrets/nextcloud-secrets.json.age b/secrets/nextcloud-secrets.json.age new file mode 100644 index 0000000..02d170d Binary files /dev/null and b/secrets/nextcloud-secrets.json.age differ diff --git a/secrets/secrets.nix b/secrets/secrets.nix index ba71b7a..a90cd74 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -1,29 +1,35 @@ let - io-user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3Y0PVpGfJHonqDS7qoCFhqzUvqGq9I9sax+F9e/5cs"; - 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 AAAAC3NzaC1lZDI1NTE5AAAAIIjXcqQqlu03x2VVTdWOyxtKRszXAKX0AxTkGvF1oeJL"; - 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"; - trantor-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINkGuGLZPnYJbCGY4BhJ9uTupp6ruuR1NZ7FEYEaLPA7"; - trantor = [ trantor-host ]; - - desktops = io ++ rotterdam; - servers = alexandria ++ trantor; - all-hosts = desktops ++ servers; + trantor = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIh/2u5pr/iPVeavlsor5hbTtsgUfP1JpzZVco2YQAo3 root@trantor"; in + { - "cloudflare.age".publicKeys = all-hosts; - "webdav.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/secrets/webdav.age b/secrets/webdav.age deleted file mode 100644 index 93bd850..0000000 --- a/secrets/webdav.age +++ /dev/null @@ -1,15 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 Kfdnog 9oKx6Oz/J/QJ0mmgoLX5AUx0sFdxnPVnjF42bElPSXA -BJ6h4lHGDsf1Npc4bwkvz5htGRT/x/b2bs9WFM2W/pc --> ssh-ed25519 SP9f6A T5t4apynXLYN/4YEvaHRCI28rrKzet4r6LrbAye5VGk -BsXkZYBxG9zcfLYCd9H0+LW078oCDyYx9zG+DPfE7bA --> ssh-ed25519 8YSAiw RY0YR30qyJPvhy7eTJLoj2JXpH9qHP43fJaHilJykXM -E5/P0Egz/LKwEhYLYd5Cnrat47gnYn93yDSeYgLi934 --> ssh-ed25519 7cojTQ qTCTw7CjilThFLmXYph4YhVBhnk1DpnFCGwgioo/XB0 -N31nZ8nInQuddLD3b0bxI5Es/pTvTQD8nz0f/AZtNFg --> ssh-ed25519 J6tVTA 7OawDsWwtVxu76ZgF0dFclMr19sBNdtu7H+Tr7Pd+SQ -hhVKcscIKIH1WChhRo/RYqUWy1rgs/EKnlHr9uY7QrQ --> ssh-ed25519 Kl5yTQ +i2Q3uNHw1jAVH76NHy4QbjCc6sBBYjsbr7w4mLaHW4 -JOJ02zU0+IxlbXMBsW4UrvzvLUbifdzABBNL+bc0bBs ---- W40oEFdBUKbi0teNTc6B1sX0ReHDvkIJcBm1dlROnk8 -zҼCn箱e7{{N6az"EHB/BYbD \ No newline at end of file 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 5ef9e0a..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 90231a2..0000000 --- a/users/modules/programs.nix +++ /dev/null @@ -1,103 +0,0 @@ -{ - config, - hostType, - lib, - pkgs, - ... -}: - -{ - config = lib.mkMerge [ - # Common configuration - { - home = { - sessionVariables = { - EDITOR = "hx"; - }; - }; - - programs = { - bash = { - enable = true; - historyFile = "~/.cache/bash_history"; - }; - - helix = { - enable = true; - package = pkgs.evil-helix; - settings = { - editor = { - file-picker.hidden = false; - idle-timeout = 0; - line-number = "relative"; - cursor-shape = { - normal = "block"; - insert = "bar"; - select = "underline"; - }; - soft-wrap.enable = true; - auto-format = true; - indent-guides.render = true; - }; - keys.normal.space = { - o = "file_picker_in_current_buffer_directory"; - }; - }; - }; - - 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 = "sponge"; - src = pkgs.fetchFromGitHub { - owner = "meaningful-ooo"; - repo = "sponge"; - rev = "384299545104d5256648cee9d8b117aaa9a6d7be"; - sha256 = "sha256-MdcZUDRtNJdiyo2l9o5ma7nAX84xEJbGFhAVhK+Zm1w="; - }; - } - { - name = "z"; - src = pkgs.fetchFromGitHub { - owner = "jethrokuan"; - repo = "z"; - rev = "85f863f20f24faf675827fb00f3a4e15c7838d76"; - sha256 = "sha256-+FUBM7CodtZrYKqU542fQD+ZDGrd2438trKM0tIESs0="; - }; - } - ]; - }; - }; - - } - - # Server specific configuration - (lib.mkIf hostType.isServer { - }) - - # Workstation specific configuration - (lib.mkIf hostType.isWorkstation { - programs.rio = { - enable = true; - settings = { - padding-x = 8; - padding-y = [ - 8 - 8 - ]; - }; - }; - }) - ]; -} 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 38311a6..0000000 --- a/users/modules/user/home.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ - gtk = { - enable = true; - 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 a024663..0000000 --- a/users/modules/user/programs.nix +++ /dev/null @@ -1,133 +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 - ]; - }; - }; - }) - ]; -} 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; + } + ]; +}