14 Commits

49 changed files with 1019 additions and 1168 deletions

298
flake.lock generated
View File

@@ -29,11 +29,11 @@
"systems": "systems_2" "systems": "systems_2"
}, },
"locked": { "locked": {
"lastModified": 1758645700, "lastModified": 1758874004,
"narHash": "sha256-7VHPjP/FDqx3EctIXqUssh8GC9ldXq/eNMX21uVkI8c=", "narHash": "sha256-+RUCBtT01Z595NpGc6Tvms+dJ/C/cn1zdjT9+gE6dbU=",
"owner": "anyrun-org", "owner": "anyrun-org",
"repo": "anyrun", "repo": "anyrun",
"rev": "8cf7bd9de48e50cf1d662a56af28c0d13da91761", "rev": "3c571bc1514c4211d1d6c011a1d482f97efd9c5f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -50,11 +50,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758040471, "lastModified": 1758817837,
"narHash": "sha256-jsFBGoLiciAFRs5Fi4eOvbsXtf2tLyYh+OiRhV6BGI4=", "narHash": "sha256-J3Jl4Z8SJHj+ogyohPeypT5LmQtCupdBteFezwiEZ9E=",
"owner": "anyrun-org", "owner": "anyrun-org",
"repo": "anyrun-provider", "repo": "anyrun-provider",
"rev": "6631af0ecb8f245cbf88e972d1522f747d6cd883", "rev": "b20650aa1bf80ae86b5bf5253d21fc0ddb7985c7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -114,11 +114,11 @@
"uv2nix": "uv2nix" "uv2nix": "uv2nix"
}, },
"locked": { "locked": {
"lastModified": 1758177015, "lastModified": 1759322529,
"narHash": "sha256-PCUWdbaxayY3YfSjVlyddBMYoGvSaRysd5AmZ8gqSFs=", "narHash": "sha256-yiv/g/tiJI3PI95F7vhTnaf1TDsIkFLrmmFTjWfb6pQ=",
"owner": "nix-community", "owner": "nix-community",
"repo": "authentik-nix", "repo": "authentik-nix",
"rev": "4c626ed84cc0f1278bfba0f534efd6cba2788d75", "rev": "69fac057b2e553ee17c9a09b822d735823d65a6c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -130,16 +130,16 @@
"authentik-src": { "authentik-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1758035356, "lastModified": 1759190535,
"narHash": "sha256-DkvxDwHCfSqEpZ9rRXNR8MP0Mz/y1kHAr38exrHQ39c=", "narHash": "sha256-pIzDaoDWc58cY/XhsyweCwc4dfRvkaT/zqsV1gDSnCI=",
"owner": "goauthentik", "owner": "goauthentik",
"repo": "authentik", "repo": "authentik",
"rev": "680feaefa17934471a6b33ebc35caf5b64120404", "rev": "8d3a289d12c7de2f244c76493af7880f70d08af2",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "goauthentik", "owner": "goauthentik",
"ref": "version/2025.8.3", "ref": "version/2025.8.4",
"repo": "authentik", "repo": "authentik",
"type": "github" "type": "github"
} }
@@ -153,11 +153,11 @@
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1758642505, "lastModified": 1759348172,
"narHash": "sha256-056XfEHlYdBKU2RtN4R+9m2nzL588TCZ8AsIviWONRg=", "narHash": "sha256-ZPUJX2ZA0ndcHndIA/S/nRESIJV0rifPr91SUpzJtEM=",
"owner": "chaotic-cx", "owner": "chaotic-cx",
"repo": "nyx", "repo": "nyx",
"rev": "0fe60fa161631289a051fef36dfaab28465ddc7b", "rev": "dd1af56ad79c965ee20c236ba6adbb2135ac02af",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -212,11 +212,11 @@
"rust-analyzer-src": "rust-analyzer-src" "rust-analyzer-src": "rust-analyzer-src"
}, },
"locked": { "locked": {
"lastModified": 1758695884, "lastModified": 1759473677,
"narHash": "sha256-rnHjtBRkcwRkrUZxg0RqN1qWTG+QC/gj4vn9uzEkBww=", "narHash": "sha256-9AFDP5AhXe06aXXPsV7bDGH7KA9Wo4uUtK7pRrsxuFQ=",
"owner": "nix-community", "owner": "nix-community",
"repo": "fenix", "repo": "fenix",
"rev": "9cdb79384d02234fb2868eba6c7d390253ef6f83", "rev": "8532b07ced6a95d57650124c79534a3c770431ab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -312,11 +312,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1754487366, "lastModified": 1756770412,
"narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=", "narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18", "rev": "4524271976b625a4a605beefd893f270620fd751",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -332,11 +332,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1756770412, "lastModified": 1759362264,
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=", "narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "4524271976b625a4a605beefd893f270620fd751", "rev": "758cf7296bee11f1706a574c77d072b8a7baa881",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -392,11 +392,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1756770412, "lastModified": 1759362264,
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=", "narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "4524271976b625a4a605beefd893f270620fd751", "rev": "758cf7296bee11f1706a574c77d072b8a7baa881",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -571,11 +571,11 @@
}, },
"hardware": { "hardware": {
"locked": { "locked": {
"lastModified": 1758663926, "lastModified": 1759261527,
"narHash": "sha256-6CFdj7Xs616t1W4jLDH7IohAAvl5Dyib3qEv/Uqw1rk=", "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=",
"owner": "nixos", "owner": "nixos",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "170ff93c860b2a9868ed1e1102d4e52cb3d934e1", "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -590,11 +590,11 @@
"rust-overlay": "rust-overlay_2" "rust-overlay": "rust-overlay_2"
}, },
"locked": { "locked": {
"lastModified": 1758722153, "lastModified": 1759201995,
"narHash": "sha256-q0t19uo2qGy9iA+pvhQ97jQ4jMWJfG3a3diLspPeBAQ=", "narHash": "sha256-3STv6fITv8Ar/kl0H7vIA7VV0d2gyLh8UL0BOiVacXg=",
"owner": "helix-editor", "owner": "helix-editor",
"repo": "helix", "repo": "helix",
"rev": "ed08fbd4102e320bf96f2af2854b9de77df7a104", "rev": "bfcbef10c513108c7b43317569416c2eefc4ed44",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -610,11 +610,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758719930, "lastModified": 1759337100,
"narHash": "sha256-DgHe1026Ob49CPegPMiWj1HNtlMTGQzfSZQQVlHC950=", "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "142acd7a7d9eb7f0bb647f053b4ddfd01fdfbf1d", "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -652,11 +652,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758464306, "lastModified": 1759261733,
"narHash": "sha256-i56XRXqjwJRdVYmpzVUQ0ktqBBHqNzQHQMQvFRF/acQ=", "narHash": "sha256-G104PUPKBgJmcu4NWs0LUaPpSOTD4jiq4mamLWu3Oc0=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "939e91e1cff1f99736c5b02529658218ed819a2a", "rev": "5a21f4819ee1be645f46d6b255d49f4271ef6723",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -803,11 +803,11 @@
"xdph": "xdph" "xdph": "xdph"
}, },
"locked": { "locked": {
"lastModified": 1758654510, "lastModified": 1759399554,
"narHash": "sha256-V4hLuM9uB4ecz0sFnnrt0idxpw0kGIw+6tLmBw2X0u8=", "narHash": "sha256-FsFugHj7He5siEcmoRUdMKHB8uMzyneK/fynPS57W4E=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland", "repo": "hyprland",
"rev": "ec9a72d9fbe8372c4cc4e86966f6b13d178b0bba", "rev": "3bcfa94ee4189faaa4daf661949e88cf28c00d94",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -824,11 +824,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758531979, "lastModified": 1759238633,
"narHash": "sha256-iRv5afKzuu6SkwztqMwZ33161CzBJsyeRHp0uviN9TI=", "narHash": "sha256-4/AtRCQKXuU49ozZZouWuC+T7vCjQh9HAz3N8Tt5OZE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "contrib", "repo": "contrib",
"rev": "de79078fd59140067e53cd00ebdf17f96ce27846", "rev": "513d71d3f42c05d6a38e215382c5a6ce971bd77d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1006,11 +1006,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758124489, "lastModified": 1759492718,
"narHash": "sha256-YiVF/8Me3vVKJBEgGpQhn0HF09EWfXZGaWLzAaJBrO4=", "narHash": "sha256-Mxi/LyyHE9VKUnBs4y1hXO+wRqukZJjbx/igqKQxkQk=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlock", "repo": "hyprlock",
"rev": "7f769fa993cb492982d7bf25676c68ddbcc0268e", "rev": "3cb799b1842016c85cca2db66fa502b8179cf0fe",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1191,11 +1191,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1757230583, "lastModified": 1759217228,
"narHash": "sha256-4uqu7sFPOaVTCogsxaGMgbzZ2vK40GVGMfUmrvK3/LY=", "narHash": "sha256-P13ExJlhMVkrc5LxZLNkIJZhjNYo3LLXnxDsUNrdnMQ=",
"owner": "Jovian-Experiments", "owner": "Jovian-Experiments",
"repo": "Jovian-NixOS", "repo": "Jovian-NixOS",
"rev": "fc3960e6c32c9d4f95fff2ef84444284d24d3bea", "rev": "e52c15ab25f7dc68dde527c8df5bfa9d80d8e64f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1229,11 +1229,11 @@
}, },
"mnw": { "mnw": {
"locked": { "locked": {
"lastModified": 1756659871, "lastModified": 1758834834,
"narHash": "sha256-v6Rh4aQ6RKjM2N02kK9Usn0Ix7+OY66vNpeklc1MnGE=", "narHash": "sha256-Y7IvY4F8vajZyp3WGf+KaiIVwondEkMFkt92Cr9NZmg=",
"owner": "Gerg-L", "owner": "Gerg-L",
"repo": "mnw", "repo": "mnw",
"rev": "ed6cc3e48557ba18266e598a5ebb6602499ada16", "rev": "cfbc7d1cc832e318d0863a5fc91d940a96034001",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1268,62 +1268,6 @@
"type": "github" "type": "github"
} }
}, },
"niri": {
"inputs": {
"niri-stable": "niri-stable",
"niri-unstable": "niri-unstable",
"nixpkgs": "nixpkgs_8",
"nixpkgs-stable": "nixpkgs-stable",
"xwayland-satellite-stable": "xwayland-satellite-stable",
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
},
"locked": {
"lastModified": 1758697829,
"narHash": "sha256-1pO4A16ssvjHNyHilpvxo15mBkAifCSOiLs3hBlrYdU=",
"owner": "sodiboo",
"repo": "niri-flake",
"rev": "9dbeb8f613d2da107bff8375c2db7182a2bb79bb",
"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": 1758691861,
"narHash": "sha256-CYgoGrY/Fx+hjzp8graTxJw1M7mn1f2jBkK26M04T0s=",
"owner": "YaLTeR",
"repo": "niri",
"rev": "e837e39623457dc5ad29c34a5ce4d4616e5fbf1e",
"type": "github"
},
"original": {
"owner": "YaLTeR",
"repo": "niri",
"type": "github"
}
},
"nix-gaming": { "nix-gaming": {
"inputs": { "inputs": {
"flake-parts": [ "flake-parts": [
@@ -1334,11 +1278,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758678659, "lastModified": 1759455985,
"narHash": "sha256-Ff5IFCEABf3CStKvf8MqJe7jwrHk2J8swdYTrwOj9dk=", "narHash": "sha256-8qDv7NXH3fj1CDXed7c7vJLtrRKDZSo0x6TaWSfelVg=",
"owner": "fufexan", "owner": "fufexan",
"repo": "nix-gaming", "repo": "nix-gaming",
"rev": "6418c314274a8ce27078402ab1fbac7c06da7a36", "rev": "eb5ab503cbd3cb386e8d85a55a9faed73ec7dc37",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1401,45 +1345,13 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-stable": {
"locked": {
"lastModified": 1758589230,
"narHash": "sha256-zMTCFGe8aVGTEr2RqUi/QzC1nOIQ0N1HRsbqB4f646k=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d1d883129b193f0b495d75c148c2c3a7d95789a0",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_10": {
"locked": {
"lastModified": 1756696532,
"narHash": "sha256-6FWagzm0b7I/IGigOv9pr6LL7NQ86mextfE8g8Q6HBg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "58dcbf1ec551914c3756c267b8b9c8c86baa1b2f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1755186698, "lastModified": 1758690382,
"narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", "rev": "e643668fd71b949c53f8626614b21ff71a07379d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1451,11 +1363,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1758633633, "lastModified": 1759147044,
"narHash": "sha256-20FVSEcXWV0P1A/1EDMUH7UVFvktg/ltBNqHJmoQTO8=", "narHash": "sha256-3ZPFytJOcLjTChljeaGgoaNj+tOqzgEpqZAvRe3bU90=",
"owner": "PedroHLC", "owner": "PedroHLC",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "36740bcdb7ea5625132575da3c627032b812c236", "rev": "18e83bbe13aa50992777832b52bd0e0d8585fb3b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1531,11 +1443,11 @@
}, },
"nixpkgs_8": { "nixpkgs_8": {
"locked": { "locked": {
"lastModified": 1758427187, "lastModified": 1759381078,
"narHash": "sha256-pHpxZ/IyCwoTQPtFIAG2QaxuSm8jWzrzBGjwQZIttJc=", "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "554be6495561ff07b6c724047bdd7e0716aa7b46", "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1547,16 +1459,16 @@
}, },
"nixpkgs_9": { "nixpkgs_9": {
"locked": { "locked": {
"lastModified": 1758427187, "lastModified": 1759386674,
"narHash": "sha256-pHpxZ/IyCwoTQPtFIAG2QaxuSm8jWzrzBGjwQZIttJc=", "narHash": "sha256-wg1Lz/1FC5Q13R+mM5a2oTV9TA9L/CHHTm3/PiLayfA=",
"owner": "NixOS", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "554be6495561ff07b6c724047bdd7e0716aa7b46", "rev": "625ad6366178f03acd79f9e3822606dd7985b657",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "nixos",
"ref": "nixos-unstable", "ref": "nixpkgs-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@@ -1566,15 +1478,15 @@
"flake-compat": "flake-compat_5", "flake-compat": "flake-compat_5",
"flake-parts": "flake-parts_5", "flake-parts": "flake-parts_5",
"mnw": "mnw", "mnw": "mnw",
"nixpkgs": "nixpkgs_10", "nixpkgs": "nixpkgs_9",
"systems": "systems_5" "systems": "systems_5"
}, },
"locked": { "locked": {
"lastModified": 1758271661, "lastModified": 1759469269,
"narHash": "sha256-ENqd2/33uP5vB44ClDjjAV+J78oF8q1er4QUZuT8Z7g=", "narHash": "sha256-DP833ejGUNRRHsJOB3WRTaWWXLNucaDga2ju/fGe+sc=",
"owner": "notashelf", "owner": "notashelf",
"repo": "nvf", "repo": "nvf",
"rev": "b7571df4d6e9ac08506a738ddceeec0b141751b0", "rev": "e48638aef3a95377689de0ef940443c64f870a09",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1702,9 +1614,8 @@
"hyprlock": "hyprlock", "hyprlock": "hyprlock",
"hyprpaper": "hyprpaper", "hyprpaper": "hyprpaper",
"lanzaboote": "lanzaboote", "lanzaboote": "lanzaboote",
"niri": "niri",
"nix-gaming": "nix-gaming", "nix-gaming": "nix-gaming",
"nixpkgs": "nixpkgs_9", "nixpkgs": "nixpkgs_8",
"nvf": "nvf", "nvf": "nvf",
"systems": "systems_6", "systems": "systems_6",
"treefmt-nix": "treefmt-nix", "treefmt-nix": "treefmt-nix",
@@ -1715,11 +1626,11 @@
"rust-analyzer-src": { "rust-analyzer-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1758620797, "lastModified": 1759301569,
"narHash": "sha256-Ly4rHgrixFMBnkbMursVt74mxnntnE6yVdF5QellJ+A=", "narHash": "sha256-7StxDed3v2fAWLkl+Hse9FlpjT7Dk7Cn/4vxTFyEhIg=",
"owner": "rust-lang", "owner": "rust-lang",
"repo": "rust-analyzer", "repo": "rust-analyzer",
"rev": "905641f3520230ad6ef421bcf5da9c6b49f2479b", "rev": "472037b789cf593172d6adf3b8d9f7a429f6cd9b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1737,11 +1648,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758422215, "lastModified": 1759286284,
"narHash": "sha256-JvF5SXhp1wBHbfEVAWgJCDVSO8iknfDqXfqMch5YWg0=", "narHash": "sha256-JLdGGc4XDutzSD1L65Ni6Ye+oTm8kWfm0KTPMcyl7Y4=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "6f3988eb5885f1e2efa874a480d91de09a7f9f0b", "rev": "f6f2da475176bb7cff51faae8b3fe879cd393545",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -2005,39 +1916,6 @@
"type": "github" "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": 1758577423,
"narHash": "sha256-sB2GAOjhjoWnjU6A/uHNJiY6O3UeztV5pJAN2g1FkXU=",
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"rev": "03368548ba745e17a85bd631613a59cb2d8469a4",
"type": "github"
},
"original": {
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"type": "github"
}
},
"zen-browser": { "zen-browser": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -2045,11 +1923,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758575291, "lastModified": 1759180079,
"narHash": "sha256-Y/sVWFUNVI663tnNvMZ/n3bLsg8V7idA4M2eaoHxmhs=", "narHash": "sha256-5hqTGqAKcLEumY3tqOtHK17CA6RkzS1I0EGKfuoyb58=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "ee14b24cfe16dd9bc02aa25409a2a4349ed361c9", "rev": "d4a254b38c7ac2b99931220d767610adfa3a57fe",
"revCount": 131, "revCount": 135,
"type": "git", "type": "git",
"url": "https://git.sr.ht/~canasta/zen-browser-flake" "url": "https://git.sr.ht/~canasta/zen-browser-flake"
}, },

View File

@@ -1,7 +1,8 @@
{ {
description = "cnix nix"; description = "cnix nix";
outputs = inputs: outputs =
inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } { inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ systems = [
"x86_64-linux" "x86_64-linux"
@@ -16,11 +17,13 @@
./fmt-hooks.nix ./fmt-hooks.nix
]; ];
perSystem = { perSystem =
{
config, config,
pkgs, pkgs,
... ...
}: { }:
{
devShells.default = pkgs.mkShell { devShells.default = pkgs.mkShell {
packages = [ packages = [
pkgs.git pkgs.git
@@ -144,8 +147,6 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
niri.url = "github:sodiboo/niri-flake";
# Custom # Custom
tuirun = { tuirun = {
url = "git+https://git.sr.ht/~canasta/tuirun"; url = "git+https://git.sr.ht/~canasta/tuirun";

View File

@@ -4,8 +4,10 @@
homeImports, homeImports,
self, self,
... ...
}: { }:
flake.nixosConfigurations = let {
flake.nixosConfigurations =
let
cLib = import ../lib inputs.nixpkgs.lib; cLib = import ../lib inputs.nixpkgs.lib;
userConfig = "${self}/home"; userConfig = "${self}/home";
systemConfig = "${self}/system"; systemConfig = "${self}/system";
@@ -35,7 +37,8 @@
smodPath smodPath
; ;
}; };
in { in
{
kima = nixosSystem { kima = nixosSystem {
inherit specialArgs; inherit specialArgs;
modules = [ modules = [

View File

@@ -5,6 +5,7 @@
variant = "latest"; variant = "latest";
hardware = [ "amd" ]; hardware = [ "amd" ];
extraKernelParams = [ ]; extraKernelParams = [ ];
amdOverdrive.enable = true;
}; };
loader = { loader = {
default = { default = {
@@ -214,6 +215,9 @@
scheduler = "scx_lavd"; scheduler = "scx_lavd";
flags = "--performance"; flags = "--performance";
}; };
tailscale = {
enable = true;
};
udisks = { udisks = {
enable = true; enable = true;
}; };

View File

@@ -39,6 +39,7 @@ in {
"share" "share"
"jellyfin" "jellyfin"
"render" "render"
"traefik"
]; ];
}; };

View File

@@ -213,6 +213,9 @@
scheduler = "scx_lavd"; scheduler = "scx_lavd";
flags = "--performance"; flags = "--performance";
}; };
tailscale = {
enable = false;
};
udisks = { udisks = {
enable = true; enable = true;
}; };

View File

@@ -8,25 +8,15 @@
uid = 994; uid = 994;
gid = 993; gid = 993;
authentik = { nginx = {
enable = true; enable = true;
}; };
traefik = {
enable = true;
};
www = {
enable = true;
url = "cnst.dev";
};
gitea = { gitea = {
enable = true; enable = true;
}; };
unbound = { unbound = {
enable = true; enable = true;
}; };
acme = {
enable = false;
};
homepage-dashboard = { homepage-dashboard = {
enable = true; enable = true;
}; };
@@ -52,7 +42,11 @@
enable = true; enable = true;
}; };
jellyfin = { jellyfin = {
enable = true; enable = false;
cloudflared = {
tunnelId = "234811e2-bc86-44b2-9abd-493686e25704";
credentialsFile = config.age.secrets.jellyfinCloudflared.path;
};
}; };
uptime-kuma = { uptime-kuma = {
enable = true; enable = true;
@@ -65,6 +59,22 @@
credentialsFile = config.age.secrets.vaultwardenCloudflared.path; credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
}; };
}; };
www = {
enable = false;
url = "cnst.dev";
cloudflared = {
tunnelId = "e5076186-efb7-405a-998c-6155af7fb221";
credentialsFile = config.age.secrets.wwwCloudflared.path;
};
};
authentik = {
enable = true;
url = "auth.cnst.dev";
cloudflared = {
tunnelId = "b66f9368-db9e-4302-8b48-527cda34a635";
credentialsFile = config.age.secrets.authentikCloudflared.path;
};
};
nextcloud = { nextcloud = {
enable = true; enable = true;
adminpassFile = config.age.secrets.nextcloudAdminPass.path; adminpassFile = config.age.secrets.nextcloudAdminPass.path;
@@ -82,14 +92,14 @@
enable = true; enable = true;
gluetun.enable = true; gluetun.enable = true;
qbittorrent = { qbittorrent = {
enable = true; enable = false;
port = 8080; port = 8387;
}; };
slskd = { slskd = {
enable = true; enable = true;
}; };
pihole = { pihole = {
enable = true; enable = false;
port = 8053; port = 8053;
}; };
}; };

View File

@@ -11,9 +11,6 @@
unbound = { unbound = {
enable = true; enable = true;
}; };
acme = {
enable = true;
};
homepage-dashboard = { homepage-dashboard = {
enable = false; enable = false;
}; };

View File

@@ -100,7 +100,6 @@
./nixos/services/virtualisation ./nixos/services/virtualisation
./nixos/services/locate ./nixos/services/locate
./nixos/services/mullvad ./nixos/services/mullvad
./nixos/services/mullvad-netns
./nixos/services/nfs ./nixos/services/nfs
./nixos/services/nix-ld ./nixos/services/nix-ld
./nixos/services/openssh ./nixos/services/openssh
@@ -114,6 +113,7 @@
./nixos/services/udisks ./nixos/services/udisks
./nixos/services/xserver ./nixos/services/xserver
./nixos/services/zram ./nixos/services/zram
./nixos/services/tailscale
./nixos/system/fonts ./nixos/system/fonts
./nixos/system/locale ./nixos/system/locale
@@ -123,7 +123,6 @@
server = { server = {
imports = [ imports = [
./server ./server
./server/acme
./server/fail2ban ./server/fail2ban
./server/homepage-dashboard ./server/homepage-dashboard
./server/nextcloud ./server/nextcloud
@@ -142,7 +141,7 @@
./server/keepalived ./server/keepalived
./server/gitea ./server/gitea
./server/postgres ./server/postgres
./server/traefik ./server/nginx
./server/www ./server/www
./server/authentik ./server/authentik
]; ];

View File

@@ -7,6 +7,9 @@
let let
inherit (lib) mkIf mkEnableOption; inherit (lib) mkIf mkEnableOption;
cfg = config.home.programs.mpv; cfg = config.home.programs.mpv;
inherit (config.xdg.userDirs) videos;
inherit (config.home) homeDirectory;
shaders_dir = "${pkgs.mpv-shim-default-shaders}/share/mpv-shim-default-shaders/shaders";
in in
{ {
options = { options = {
@@ -15,8 +18,71 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
programs.mpv = { programs.mpv = {
enable = true; enable = true;
defaultProfiles = [ "gpu-hq" ]; config = {
scripts = [ pkgs.mpvScripts.mpris ]; profile = "gpu-hq";
gpu-context = "wayland";
vo = "gpu-next";
video-sync = "display-resample";
interpolation = true;
tscale = "oversample";
fullscreen = false;
keep-open = true;
sub-auto = "fuzzy";
sub-font = "Noto Sans Medium";
sub-blur = 10;
screenshot-format = "png";
title = "\${filename} - mpv";
script-opts = "osc-title=\${filename},osc-boxalpha=150,osc-visibility=never,osc-boxvideo=yes";
ytdl-format = "bestvideo[height<=?1440]+bestaudio/best";
ao = "pipewire";
alang = "eng,en";
slang = "eng,en,enUS";
glsl-shader = "${homeDirectory}/.config/mpv/shaders/FSR.glsl";
scale = "lanczos";
cscale = "lanczos";
dscale = "mitchell";
deband = "yes";
scale-antiring = 1;
osc = "no";
osd-on-seek = "no";
osd-bar = "no";
osd-bar-w = 30;
osd-bar-h = "0.2";
osd-duration = 750;
really-quiet = "yes";
autofit = "65%";
};
bindings = {
"ctrl+a" = "script-message osc-visibility cycle";
};
scripts = with pkgs.mpvScripts; [
mpris
uosc
thumbfast
sponsorblock
autocrop
];
};
programs.yt-dlp = {
enable = true;
extraConfig = ''
-o ${videos}/youtube/%(title)s.%(ext)s
'';
};
home = {
file = {
".config/mpv/shaders/FSR.glsl".source = "${shaders_dir}/FSR.glsl";
};
packages = with pkgs; [
jellyfin-mpv-shim
];
}; };
}; };
} }

View File

@@ -5,7 +5,12 @@
... ...
}: }:
let let
inherit (lib) mkOption types; inherit (lib)
mkOption
types
mkEnableOption
mkIf
;
cfg = config.nixos.boot.kernel; cfg = config.nixos.boot.kernel;
hasHardware = hw: builtins.elem hw cfg.hardware; hasHardware = hw: builtins.elem hw cfg.hardware;
@@ -37,8 +42,11 @@ in
); );
default = [ ]; default = [ ];
description = "List of hardware types (e.g. GPU and CPU vendors) to configure kernel settings for."; description = "List of hardware types (e.g. GPU and CPU vendors) to configure kernel settings for.";
}; };
amdOverdrive.enable = mkEnableOption "Enable AMD pstate/overdrive";
extraKernelParams = mkOption { extraKernelParams = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ ]; default = [ ];
@@ -74,7 +82,7 @@ in
"quiet" "quiet"
"splash" "splash"
] ]
++ (if hasHardware "amd" then [ "amd_pstate=active" ] else [ ]) ++ (if hasHardware "amd" then [ ] else [ ])
++ (if hasHardware "intel" then [ ] else [ ]) ++ (if hasHardware "intel" then [ ] else [ ])
++ (if hasHardware "nvidia" then [ ] else [ ]) ++ (if hasHardware "nvidia" then [ ] else [ ])
++ cfg.extraKernelParams; ++ cfg.extraKernelParams;
@@ -85,5 +93,6 @@ in
++ (if hasHardware "nvidia" then [ "nouveau" ] else [ ]) ++ (if hasHardware "nvidia" then [ "nouveau" ] else [ ])
++ cfg.extraBlacklistedModules; ++ cfg.extraBlacklistedModules;
}; };
hardware.amdgpu.overdrive.enable = mkIf cfg.amdOverdrive.enable true;
}; };
} }

View File

@@ -89,7 +89,8 @@ in
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable (mkMerge [
{ {
hardware.graphics = { hardware = {
graphics = {
enable = true; enable = true;
enable32Bit = true; enable32Bit = true;
extraPackages = flatten ( extraPackages = flatten (
@@ -121,6 +122,7 @@ in
extraPackages32 = flatten (concatMap (_: commonPackages32) cfg.vendors); extraPackages32 = flatten (concatMap (_: commonPackages32) cfg.vendors);
}; };
};
environment.systemPackages = flatten ( environment.systemPackages = flatten (
concatMap ( concatMap (
@@ -145,10 +147,6 @@ in
); );
} }
(mkIf (hasVendor "amd") {
hardware.amdgpu.overdrive.enable = true;
})
(mkIf (hasVendor "nvidia") { (mkIf (hasVendor "nvidia") {
hardware.nvidia = { hardware.nvidia = {
package = package =

View File

@@ -1,6 +1,5 @@
{ {
config, config,
inputs,
lib, lib,
pkgs, pkgs,
... ...
@@ -14,22 +13,22 @@ in
nixos.programs.niri.enable = mkEnableOption "Enables niri"; nixos.programs.niri.enable = mkEnableOption "Enables niri";
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
nixpkgs.overlays = [ inputs.niri.overlays.niri ];
environment = { environment = {
variables = { variables = {
DISPLAY = ":0";
NIXOS_OZONE_WL = "1"; NIXOS_OZONE_WL = "1";
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
}; };
systemPackages = with pkgs; [ systemPackages = with pkgs; [
xwayland-satellite-unstable xwayland-satellite
wl-clipboard wl-clipboard
wayland-utils wayland-utils
xdg-utils
]; ];
}; };
systemd.user.services.niri-flake-polkit.enable = false; systemd.user.services.niri-flake-polkit.enable = false;
programs.niri = { programs.niri = {
enable = true; enable = true;
package = pkgs.niri-unstable;
}; };
}; };
} }

View File

@@ -3,17 +3,16 @@
config, config,
lib, lib,
... ...
}: }: let
let inherit
inherit (lib) (lib)
mkIf mkIf
mkOption mkOption
mkMerge mkMerge
types types
; ;
cfg = config.nixos.programs.pkgs; cfg = config.nixos.programs.pkgs;
in in {
{
options = { options = {
nixos.programs.pkgs = { nixos.programs.pkgs = {
enable = mkOption { enable = mkOption {
@@ -51,8 +50,7 @@ in
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
environment.systemPackages = environment.systemPackages = with pkgs;
with pkgs;
mkMerge [ mkMerge [
[ [
pciutils pciutils
@@ -114,6 +112,8 @@ in
helix helix
zfs zfs
zfstools zfstools
cron
acme-sh
]) ])
(mkIf cfg.dev.enable [ (mkIf cfg.dev.enable [

View File

@@ -70,23 +70,15 @@ in {
secrets = { secrets = {
cloudflareFirewallApiKey.file = "${self}/secrets/cloudflareFirewallApiKey.age"; cloudflareFirewallApiKey.file = "${self}/secrets/cloudflareFirewallApiKey.age";
cloudflareDnsApiToken.file = "${self}/secrets/cloudflareDnsApiToken.age"; cloudflareDnsApiToken.file = "${self}/secrets/cloudflareDnsApiToken.age";
cloudflareDnsCredentials.file = "${self}/secrets/cloudflareDnsCredentials.age"; # cloudflareDnsCredentials.file = "${self}/secrets/cloudflareDnsCredentials.age";
wgCredentials.file = "${self}/secrets/wgCredentials.age"; wgCredentials.file = "${self}/secrets/wgCredentials.age";
wgSobotkaPrivateKey.file = "${self}/secrets/wgSobotkaPrivateKey.age"; wgSobotkaPrivateKey.file = "${self}/secrets/wgSobotkaPrivateKey.age";
gluetunEnvironment.file = "${self}/secrets/gluetunEnvironment.age"; gluetunEnvironment.file = "${self}/secrets/gluetunEnvironment.age";
nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age";
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
homepageEnvironment.file = "${self}/secrets/homepageEnvironment.age";
pihole.file = "${self}/secrets/pihole.age";
slskd.file = "${self}/secrets/slskd.age";
}; };
}) })
(mkIf cfg.ziggy.enable { (mkIf cfg.ziggy.enable {
secrets = { secrets = {
cloudflareDnsCredentialsZiggy.file = "${self}/secrets/cloudflareDnsCredentialsZiggy.age"; cloudflareDnsCredentialsZiggy.file = "${self}/secrets/cloudflareDnsCredentialsZiggy.age";
piholeZiggy.file = "${self}/secrets/piholeZiggy.age";
}; };
}) })
(mkIf cfg.toothpc.enable { (mkIf cfg.toothpc.enable {

View File

@@ -63,7 +63,7 @@ in
settings = rec { settings = rec {
tuigreet_session = tuigreet_session =
let let
session = "${pkgs.niri-unstable}/bin/niri-session"; session = "${pkgs.niri}/bin/niri-session";
tuigreet = "${lib.getExe pkgs.tuigreet}"; tuigreet = "${lib.getExe pkgs.tuigreet}";
in in
{ {

View File

@@ -1,50 +0,0 @@
{ self, pkgs, ... }:
{
age.secrets.wgCredentials = {
file = "${self}/secrets/wgCredentials.age";
mode = "0400";
owner = "root";
group = "root";
path = "/etc/wireguard/mullvad.conf";
};
systemd.services.mullvad-netns = {
description = "WireGuard Mullvad netns for VMs";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${pkgs.writeShellScript "mullvad-netns-up" ''
set -euo pipefail
ip netns add mullvad || true
ip link add veth0 type veth peer name veth1 || true
ip link set veth1 netns mullvad
ip addr add 10.250.0.1/24 dev veth0 || true
ip link set veth0 up
ip netns exec mullvad ip addr add 10.250.0.2/24 dev veth1 || true
ip netns exec mullvad ip link set veth1 up
ip netns exec mullvad wg-quick up /etc/wireguard/mullvad.conf
ip netns exec mullvad ip route add default dev wg0 || true
nft add table ip mullvad-nat || true
nft add chain ip mullvad-nat postrouting { type nat hook postrouting priority 100 \; } || true
nft add rule ip mullvad-nat postrouting ip saddr 10.250.0.0/24 oif "wg0" masquerade || true
''}";
ExecStop = "${pkgs.writeShellScript "mullvad-netns-down" ''
set -euo pipefail
ip netns exec mullvad wg-quick down /etc/wireguard/mullvad.conf || true
ip link delete veth0 || true
ip netns delete mullvad || true
nft delete table ip mullvad-nat || true
''}";
};
# no wantedBy here -> won't start at boot
};
}

View File

@@ -0,0 +1,16 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.nixos.services.tailscale;
in {
options.nixos.services.tailscale = {
enable = mkEnableOption "Enable tailscale";
};
config = mkIf cfg.enable {
services.tailscale.enable = true;
};
}

View File

@@ -30,13 +30,19 @@ in
enable = true; enable = true;
xdgOpenUsePortal = cfg.xdgOpenUsePortal; xdgOpenUsePortal = cfg.xdgOpenUsePortal;
config = { config = {
common.default = [ "gtk" ]; common.default = [
"gtk"
"gnome"
];
hyprland.default = [ hyprland.default = [
"gtk" "gtk"
"hyprland" "hyprland"
]; ];
}; };
extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; extraPortals = with pkgs; [
xdg-desktop-portal-gtk
xdg-desktop-portal-gnome
];
}; };
}; };
} }

View File

@@ -1,84 +0,0 @@
{
config,
lib,
...
}: let
inherit (lib) mkIf mkEnableOption;
cfg = config.server.acme;
getCloudflareCredentials = hostname:
if hostname == "ziggy"
then config.age.secrets.cloudflareDnsCredentialsZiggy.path
else if hostname == "sobotka"
then config.age.secrets.cloudflareDnsCredentials.path
else throw "Unknown hostname: ${hostname}";
in {
options = {
server.acme.enable = mkEnableOption "Enables ACME";
};
config = mkIf cfg.enable {
networking.firewall = let
ports = [
80
443
];
in {
allowedTCPPorts = ports;
};
security.acme = {
acceptTerms = true;
defaults.email = config.server.email;
certs.${config.server.domain} = {
reloadServices = ["caddy.service"];
domain = "${config.server.domain}";
extraDomainNames = ["*.${config.server.domain}"];
dnsProvider = "cloudflare";
dnsResolver = "1.1.1.1:53";
dnsPropagationCheck = true;
group = config.services.caddy.group;
environmentFile = getCloudflareCredentials config.networking.hostName;
};
certs.${config.server.www.url} = {
reloadServices = ["caddy.service"];
domain = "${config.server.www.url}";
extraDomainNames = ["*.${config.server.www.url}"];
dnsProvider = "cloudflare";
dnsResolver = "1.1.1.1:53";
dnsPropagationCheck = true;
group = config.services.caddy.group;
environmentFile = getCloudflareCredentials config.networking.hostName;
};
};
services.caddy = {
enable = true;
globalConfig = ''
auto_https off
'';
virtualHosts = {
"http://${config.server.domain}" = {
extraConfig = ''
redir https://{host}{uri}
'';
};
"http://*.${config.server.domain}" = {
extraConfig = ''
redir https://{host}{uri}
'';
};
"http://${config.server.www.url}" = {
extraConfig = ''
redir https://{host}{uri}
'';
};
"http://*.${config.server.www.url}" = {
extraConfig = ''
redir https://{host}{uri}
'';
};
};
};
};
}

View File

@@ -15,7 +15,21 @@ in {
}; };
url = lib.mkOption { url = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "auth.${srv.domain}"; default = "auth.${srv.www.domain}";
};
cloudflared = {
credentialsFile = lib.mkOption {
type = lib.types.str;
example = lib.literalExpression ''
pkgs.writeText "cloudflare-credentials.json" '''
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
'''
'';
};
tunnelId = lib.mkOption {
type = lib.types.str;
example = "00000000-0000-0000-0000-000000000000";
};
}; };
homepage.name = lib.mkOption { homepage.name = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@@ -36,10 +50,26 @@ in {
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
age.secrets.authentikEnv = { age.secrets = {
authentikEnv = {
file = "${self}/secrets/authentikEnv.age"; file = "${self}/secrets/authentikEnv.age";
owner = "authentik";
}; };
authentikCloudflared = {
file = "${self}/secrets/authentikCloudflared.age";
};
};
server = {
fail2ban = lib.mkIf cfg.enable {
jails = {
authentik = {
serviceName = "authentik";
failRegex = "^.*Username or password is incorrect.*IP:\s*<HOST>";
};
};
};
};
services = { services = {
authentik = { authentik = {
enable = true; enable = true;
@@ -52,28 +82,31 @@ in {
}; };
}; };
cloudflared = {
enable = true;
tunnels.${cfg.cloudflared.tunnelId} = {
credentialsFile = cfg.cloudflared.credentialsFile;
default = "http_status:404";
ingress."${cfg.url}".service = "http://127.0.0.1:9000";
};
};
traefik = { traefik = {
dynamicConfigOptions = { dynamicConfigOptions = {
http = { http = {
middlewares = { middlewares = {
authentik = { authentik = {
forwardAuth = { forwardAuth = {
tls.insecureSkipVerify = true; # tls.insecureSkipVerify = true;
address = "https://localhost:9443/outpost.goauthentik.io/auth/traefik"; address = "https://localhost:9443/outpost.goauthentik.io/auth/traefik";
trustForwardHeader = true; trustForwardHeader = true;
authResponseHeaders = [ authResponseHeaders = [
"X-authentik-username" "X-authentik-username"
"X-authentik-groups" "X-authentik-groups"
"X-authentik-email" "X-authentik-email"
"X-authentik-name"
"X-authentik-uid"
"X-authentik-jwt" "X-authentik-jwt"
"X-authentik-meta-jwks"
"X-authentik-meta-outpost"
"X-authentik-meta-provider"
"X-authentik-meta-app"
"X-authentik-meta-version"
]; ];
timeout = "10s";
}; };
}; };
}; };
@@ -89,7 +122,7 @@ in {
routers = { routers = {
auth = { auth = {
entryPoints = ["websecure"]; entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`) || HostRegexp(`{subdomain:[a-z0-9]+}.${srv.domain}`) && PathPrefix(`/outpost.goauthentik.io/`)"; rule = "Host(`${cfg.url}`) || HostRegexp(`{subdomain:[a-z0-9]+}.${srv.www.url}`) && PathPrefix(`/outpost.goauthentik.io/`)";
service = "auth"; service = "auth";
tls.certResolver = "letsencrypt"; tls.certResolver = "letsencrypt";
}; };

View File

@@ -17,14 +17,14 @@ in {
default = ""; default = "";
type = types.str; type = types.str;
description = '' description = ''
Email name to be used to access the server services via Caddy reverse proxy Email name to be used to access the server services via NGINX reverse proxy
''; '';
}; };
domain = mkOption { domain = mkOption {
default = ""; default = "";
type = types.str; type = types.str;
description = '' description = ''
Domain name to be used to access the server services via Caddy reverse proxy Domain name to be used to access the server services via NGINX reverse proxy
''; '';
}; };
user = lib.mkOption { user = lib.mkOption {
@@ -65,6 +65,11 @@ in {
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
_module.args = {
myLib = import ./lib.nix {
inherit lib config pkgs;
};
};
users = { users = {
groups.${cfg.group} = { groups.${cfg.group} = {
gid = cfg.gid; gid = cfg.gid;
@@ -93,7 +98,7 @@ in {
"render" "render"
"input" "input"
"authentik" "authentik"
"traefik" "nginx"
]; ];
}; };
}; };

View File

@@ -4,11 +4,9 @@
config, config,
pkgs, pkgs,
... ...
}: }: let
let
cfg = config.server.fail2ban; cfg = config.server.fail2ban;
in in {
{
options.server.fail2ban = { options.server.fail2ban = {
enable = lib.mkEnableOption { enable = lib.mkEnableOption {
description = "Enable cloudflare fail2ban"; description = "Enable cloudflare fail2ban";
@@ -17,7 +15,7 @@ in
description = "File containing your API key, scoped to Firewall Rules: Edit"; description = "File containing your API key, scoped to Firewall Rules: Edit";
type = lib.types.str; type = lib.types.str;
example = lib.literalExpression '' example = lib.literalExpression ''
Authorization: Bearer Qj06My1wXJEzcW46QCyjFbSMgVtwIGfX63Ki3NOj79o= Authorization: Bearer vH6-p0y=i4w3n7TjKqZ@x8D_lR!A9b2cOezXgUuJdE5F
''' '''
''; '';
}; };
@@ -57,39 +55,39 @@ in
pkgs.jq pkgs.jq
]; ];
jails = lib.attrsets.mapAttrs (name: value: { jails =
lib.attrsets.mapAttrs (name: value: {
settings = { settings = {
bantime = "30d"; bantime = "168h";
findtime = "1h"; findtime = "30m";
enabled = true; enabled = true;
backend = "systemd"; backend = "systemd";
journalmatch = "_SYSTEMD_UNIT=${value.serviceName}.service"; journalmatch = "_SYSTEMD_UNIT=${value.serviceName}.service";
port = "http,https"; port = "http,https";
filter = "${name}"; filter = "${name}";
maxretry = 3; maxretry = value.maxRetry or 5;
action = "cloudflare-token-agenix"; action = "cloudflare-token-agenix";
}; };
}) cfg.jails; })
cfg.jails;
}; };
environment.etc = lib.attrsets.mergeAttrsList [ environment.etc = lib.attrsets.mergeAttrsList [
(lib.attrsets.mapAttrs' ( (lib.attrsets.mapAttrs' (
name: value: name: value: (lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
(lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
text = '' text = ''
[Definition] [Definition]
failregex = ${value.failRegex} failregex = ${value.failRegex}
ignoreregex = ${value.ignoreRegex} ignoreregex = ${value.ignoreRegex}
''; '';
}) })
) cfg.jails) )
cfg.jails)
{ {
"fail2ban/action.d/cloudflare-token-agenix.conf".text = "fail2ban/action.d/cloudflare-token-agenix.conf".text = let
let
notes = "Fail2Ban on ${config.networking.hostName}"; notes = "Fail2Ban on ${config.networking.hostName}";
cfapi = "https://api.cloudflare.com/client/v4/zones/${cfg.zoneId}/firewall/access_rules/rules"; cfapi = "https://api.cloudflare.com/client/v4/zones/${cfg.zoneId}/firewall/access_rules/rules";
in in ''
''
[Definition] [Definition]
actionstart = actionstart =
actionstop = actionstop =

View File

@@ -99,23 +99,6 @@ in {
}; };
}; };
services.traefik = {
dynamicConfigOptions = {
http = {
services.gitea.loadBalancer.servers = [{url = "http://127.0.0.1:5003";}];
routers = {
gitea = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)";
service = "gitea";
tls.certResolver = "letsencrypt";
# middlewares = ["authentik"];
};
};
};
};
};
server.postgresql.databases = [ server.postgresql.databases = [
{ {
database = "gitea"; database = "gitea";

View File

@@ -1,119 +0,0 @@
# taken from @jtojnar
{
config,
lib,
...
}: let
unit = "gitea";
srv = config.server;
cfg = config.server.${unit};
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
};
url = lib.mkOption {
type = lib.types.str;
default = "git.${srv.domain}";
};
port = lib.mkOption {
type = lib.types.int;
default = 5003;
description = "The port to host Gitea on.";
};
homepage.name = lib.mkOption {
type = lib.types.str;
default = "Gitea";
};
homepage.description = lib.mkOption {
type = lib.types.str;
default = "Git with a cup of tea";
};
homepage.icon = lib.mkOption {
type = lib.types.str;
default = "gitea.svg";
};
homepage.category = lib.mkOption {
type = lib.types.str;
default = "Services";
};
};
config = lib.mkIf cfg.enable {
services.${unit} = {
enable = true;
appName = "cnix code forge";
database = {
type = "postgres";
socket = "/run/postgresql";
name = "gitea";
user = "gitea";
createDatabase = false;
};
lfs = {
enable = true;
};
settings = {
cors = {
ENABLED = true;
SCHEME = "https";
ALLOW_DOMAIN = cfg.url;
};
log = {
MODE = "console";
};
mailer = {
ENABLED = false;
MAILER_TYPE = "sendmail";
FROM = "noreply+adam@cnst.dev";
SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
};
picture = {
DISABLE_GRAVATAR = true;
};
repository = {
DEFAULT_BRANCH = "main";
DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
};
indexer = {
REPO_INDEXER_ENABLED = true;
};
server = {
DOMAIN = cfg.url;
LANDING_PAGE = "explore";
HTTP_PORT = cfg.port;
ROOT_URL = "https://${cfg.url}/";
};
security = {
DISABLE_GIT_HOOKS = false;
};
service = {
DISABLE_REGISTRATION = true;
};
session = {
COOKIE_SECURE = true;
};
};
};
services.traefik.dynamicConfigOptions.http.routers."${unit}" = {
rule = "Host(`" + cfg.url + "`)";
service = "${unit}-service";
entryPoints = ["websecure"];
tls = {};
};
services.traefik.dynamicConfigOptions.http.services."${unit}-service".loadBalancer.servers = [
{url = "http://127.0.0.1:${toString cfg.port}";}
];
server.postgresql.databases = [
{
database = "gitea";
}
];
};
}

View File

@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
self,
... ...
}: let }: let
unit = "homepage-dashboard"; unit = "homepage-dashboard";
@@ -36,11 +37,16 @@ in {
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
age.secrets = {
homepageEnvironment = {
file = "${self}/secrets/homepageEnvironment.age";
};
};
services = { services = {
glances.enable = true; glances.enable = true;
${unit} = { ${unit} = {
enable = true; enable = true;
allowedHosts = srv.domain; environmentFile = config.age.secrets.homepageEnvironment.path;
settings = { settings = {
layout = [ layout = [
{ {
@@ -79,7 +85,6 @@ in {
statusStyle = "dot"; statusStyle = "dot";
hideVersion = "true"; hideVersion = "true";
}; };
widgets = [ widgets = [
{ {
openmeteo = { openmeteo = {
@@ -91,32 +96,21 @@ in {
longitude = 16.324541; longitude = 16.324541;
}; };
} }
{
datetime = {
text_size = "x1";
format = {
hour12 = false;
timeStyle = "short";
dateStyle = "long";
};
};
}
{ {
resources = { resources = {
label = ""; label = "SYSTEM";
memory = true; memory = true;
disk = ["/"]; cpu = true;
uptime = true;
}; };
} }
]; ];
services = let services = let
homepageCategories = [ homepageCategories = [
"Arr" "Arr"
"Media" "Media"
"Downloads" "Downloads"
"Services" "Services"
"Smart Home"
]; ];
hl = config.server; hl = config.server;
mergedServices = hl // hl.podman; mergedServices = hl // hl.podman;
@@ -218,23 +212,6 @@ in {
} }
]; ];
}; };
traefik = {
dynamicConfigOptions = {
http = {
services.homepage.loadBalancer.servers = [{url = "http://127.0.0.1:${toString config.services.${unit}.listenPort}";}];
routers = {
homepage = {
entryPoints = ["websecure"];
rule = "Host(`cnix.dev`)";
service = "homepage";
tls.certResolver = "letsencrypt";
# middlewares = ["authentik"];
};
};
};
};
};
}; };
}; };
} }

View File

@@ -2,23 +2,38 @@
config, config,
lib, lib,
pkgs, pkgs,
self,
... ...
}: let }: let
service = "jellyfin"; unit = "jellyfin";
cfg = config.server.${service}; cfg = config.server.${unit};
srv = config.server; srv = config.server;
in { in {
options.server.${service} = { options.server.${unit} = {
enable = lib.mkEnableOption { enable = lib.mkEnableOption {
description = "Enable ${service}"; description = "Enable ${unit}";
}; };
configDir = lib.mkOption { configDir = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "/var/lib/${service}"; default = "/var/lib/${unit}";
}; };
url = lib.mkOption { url = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "jellyfin.${srv.domain}"; default = "jellyfin.${srv.www.url}";
};
cloudflared = {
credentialsFile = lib.mkOption {
type = lib.types.str;
example = lib.literalExpression ''
pkgs.writeText "cloudflare-credentials.json" '''
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
'''
'';
};
tunnelId = lib.mkOption {
type = lib.types.str;
example = "00000000-0000-0000-0000-000000000000";
};
}; };
homepage.name = lib.mkOption { homepage.name = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@@ -38,17 +53,62 @@ in {
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.${service} = { age.secrets = {
jellyfinCloudflared = {
file = "${self}/secrets/jellyfinCloudflared.age";
owner = "${srv.user}";
group = "${srv.group}";
mode = "0400";
};
};
services = {
cloudflared = {
enable = true;
tunnels.${cfg.cloudflared.tunnelId} = {
credentialsFile = cfg.cloudflared.credentialsFile;
default = "http_status:404";
ingress."${cfg.url}".service = "http://127.0.0.1:8096";
};
};
${unit} = {
enable = true; enable = true;
user = srv.user; user = srv.user;
group = srv.group; group = srv.group;
}; };
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
jellyfin-ffmpeg jellyfin-ffmpeg
]; ];
services.traefik = { services.traefik = {
dynamicConfigOptions = { dynamicConfigOptions = {
http = { http = {
middlewares = {
secureHeaders = {
headers = {
stsSeconds = 31536000;
forceSTSHeader = true;
stsIncludeSubdomains = true;
stsPreload = true;
browserXssFilter = true;
frameDeny = true;
referrerPolicy = "no-referrer";
contentTypeNosniff = true;
customResponseHeaders = {
"Content-Security-Policy" = "default-src 'self'; img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';";
};
};
};
ratelimit = {
rateLimit = {
average = 10;
burst = 20;
};
};
};
services.jellyfin.loadBalancer.servers = [{url = "http://127.0.0.1:8096";}]; services.jellyfin.loadBalancer.servers = [{url = "http://127.0.0.1:8096";}];
routers = { routers = {
jellyfin = { jellyfin = {
@@ -56,7 +116,7 @@ in {
rule = "Host(`${cfg.url}`)"; rule = "Host(`${cfg.url}`)";
service = "jellyfin"; service = "jellyfin";
tls.certResolver = "letsencrypt"; tls.certResolver = "letsencrypt";
# middlewares = ["authentik"]; middlewares = ["authentik" "secureHeaders" "ratelimit"];
}; };
}; };
}; };

148
modules/server/lib.nix Normal file
View File

@@ -0,0 +1,148 @@
# from @jtojnar
{
config,
lib,
pkgs,
...
}: {
mkVirtualHost = {
path ? null,
config ? "",
acme ? null,
redirect ? null,
...
} @ args:
(
if lib.isString acme
then {
useACMEHost = acme;
forceSSL = true;
}
else {}
)
// (
if lib.isBool acme
then {
enableACME = acme;
forceSSL = true;
}
else {}
)
// (
if redirect != null
then {
globalRedirect = redirect;
}
else {}
)
// (
if path != null
then {
root = "/var/www/" + path;
}
else {}
)
// {
extraConfig = config;
}
// builtins.removeAttrs args [
"path"
"config"
"acme"
"redirect"
];
mkPhpPool = {
user,
debug ? false,
settings ? {},
...
} @ args:
{
inherit user;
settings =
{
"listen.owner" = "nginx";
"listen.group" = "root";
"pm" = "dynamic";
"pm.max_children" = 5;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
}
// (
lib.optionalAttrs debug {
# log worker's stdout, but this has a performance hit
"catch_workers_output" = true;
}
// settings
);
}
// builtins.removeAttrs args [
"user"
"debug"
"settings"
];
enablePHP = sockName: ''
fastcgi_pass unix:${config.services.phpfpm.pools.${sockName}.socket};
include ${config.services.nginx.package}/conf/fastcgi.conf;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
'';
/*
Adds extra options to ssh key that will only allow it to be used for rsync.
See sshd(8) manual page for details.
*/
restrictToRsync = directory: key: ''command="${pkgs.rrsync}/bin/rrsync -wo ${directory}",restrict ${key}'';
/*
Emulate systemd credentials.
Those will only be available to the user the service is running under,
not being aware of dropped euid.
http://systemd.io/CREDENTIALS/
*/
emulateCredentials = let
parseCredential = credential: let
matches = builtins.match "(.+):(.+)" credential;
in
assert lib.assertMsg (matches != null) "A credential needs to match id:value format"; {
id = builtins.elemAt matches 0;
value = builtins.elemAt matches 1;
};
parseCredentials = credentials:
builtins.map parseCredential (
if builtins.isList credentials
then credentials
else lib.splitString "," credentials
);
in
serviceConfig:
lib.mkMerge [
(builtins.removeAttrs serviceConfig [
"SetCredential"
"LoadCredential"
])
{
Environment = [
"CREDENTIALS_DIRECTORY=${
pkgs.runCommand "credentials" {} ''
mkdir "$out"
${lib.concatMapStringsSep "\n" ({
id,
value,
}: ''ln -s "${value}" "$out/${id}"'') (
parseCredentials serviceConfig.LoadCredential or []
)}
${lib.concatMapStringsSep "\n" ({
id,
value,
}: ''echo -n "${value}" > "$out/${id}"'') (
parseCredentials serviceConfig.SetCredential or []
)}
''
}"
];
}
];
}

View File

@@ -2,6 +2,7 @@
config, config,
pkgs, pkgs,
lib, lib,
self,
... ...
}: let }: let
unit = "nextcloud"; unit = "nextcloud";
@@ -45,6 +46,11 @@ in {
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
age.secrets = {
nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age";
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
};
server.fail2ban = lib.mkIf config.server.fail2ban.enable { server.fail2ban = lib.mkIf config.server.fail2ban.enable {
jails = { jails = {
nextcloud = { nextcloud = {

View File

@@ -0,0 +1,79 @@
{
lib,
config,
pkgs,
self,
myLib,
...
}: let
inherit (myLib) mkVirtualHost;
inherit (lib) mkEnableOption mkIf types;
unit = "nginx";
cfg = config.server.nginx;
srv = config.server;
in {
options.server.nginx = {
enable = mkEnableOption "Enable global NGINX reverse proxy with ACME";
};
config = mkIf cfg.enable {
age.secrets = {
nginxEnv = {
file = "${self}/secrets/nginxEnv.age";
};
};
networking.firewall.allowedTCPPorts = [80 443];
security = {
acme = {
acceptTerms = true;
defaults.email = config.server.email;
certs.${srv.domain} = {
reloadServices = ["nginx.service"];
domain = "${srv.domain}";
extraDomainNames = ["*.${srv.domain}"];
dnsProvider = "cloudflare";
dnsPropagationCheck = true;
group = config.services.nginx.group;
environmentFile = config.age.secrets.nginxEnv.path;
};
};
dhparams = {
enable = true;
params.nginx = {};
};
};
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
resolver.addresses = config.networking.nameservers;
sslDhparam = config.security.dhparams.params.nginx.path;
appendHttpConfig = ''
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 128;
'';
virtualHosts = let
labDomain = "cnix.dev";
labCert = {
useACMEHost = "cnix.dev";
forceSSL = true;
};
in {
# proxies on domain with https, only accessible within local network
"${labDomain}" =
labCert
// {
locations."/".proxyPass = "http://127.0.0.1:${toString config.services.homepage-dashboard.listenPort}";
};
};
};
users.users.nginx.extraGroups = ["acme"];
};
}

View File

@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
self,
... ...
}: let }: let
srv = config.server; srv = config.server;
@@ -33,7 +34,7 @@ in {
}; };
port = lib.mkOption { port = lib.mkOption {
type = lib.types.int; type = lib.types.int;
default = 8080; default = 8387;
description = "The port to host qBittorrent on."; description = "The port to host qBittorrent on.";
}; };
homepage.name = lib.mkOption { homepage.name = lib.mkOption {
@@ -121,6 +122,11 @@ in {
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
age.secrets = {
pihole.file = "${self}/secrets/${config.networking.hostName}Pihole.age";
slskd.file = "${self}/secrets/slskd.age";
};
virtualisation = { virtualisation = {
containers.enable = true; containers.enable = true;
podman.enable = true; podman.enable = true;
@@ -137,62 +143,6 @@ in {
]; ];
}; };
services.traefik = lib.mkMerge [
(lib.mkIf cfg.pihole.enable {
dynamicConfigOptions = {
http = {
services = {
pihole.loadBalancer.servers = [{url = "http://localhost:${toString cfg.pihole.port}";}];
};
routers = {
pihole = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.pihole.url}`)";
service = "pihole";
tls.certResolver = "letsencrypt";
};
};
};
};
})
(lib.mkIf cfg.qbittorrent.enable {
dynamicConfigOptions = {
http = {
services = {
qbittorrent.loadBalancer.servers = [{url = "http://localhost:${toString cfg.qbittorrent.port}";}];
};
routers = {
qbittorrent = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.qbittorrent.url}`)";
service = "qbittorrent";
tls.certResolver = "letsencrypt";
};
};
};
};
})
(lib.mkIf cfg.slskd.enable {
dynamicConfigOptions = {
http = {
services = {
slskd.loadBalancer.servers = [{url = "http://localhost:${toString cfg.slskd.port}";}];
};
routers = {
slskd = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.slskd.url}`)";
service = "slskd";
tls.certResolver = "letsencrypt";
};
};
};
};
})
];
virtualisation.oci-containers.containers = lib.mkMerge [ virtualisation.oci-containers.containers = lib.mkMerge [
(lib.mkIf cfg.gluetun.enable { (lib.mkIf cfg.gluetun.enable {
gluetun = { gluetun = {
@@ -200,7 +150,7 @@ in {
ports = [ ports = [
"8388:8388" "8388:8388"
"58846:58846" "58846:58846"
"8080:8080" "8387:8387"
"5030:5030" "5030:5030"
"5031:5031" "5031:5031"
"50300:50300" "50300:50300"
@@ -229,7 +179,7 @@ in {
autoStart = true; autoStart = true;
dependsOn = ["gluetun"]; dependsOn = ["gluetun"];
ports = [ ports = [
"8080:8080" "8387:8387"
"58846:58846" "58846:58846"
]; ];
extraOptions = [ extraOptions = [

View File

@@ -43,15 +43,16 @@ in {
group = srv.group; group = srv.group;
}; };
services.traefik = { services.traefik = {
# staticConfigOptions.entryPoints.${unit}.address = "127.0.0.1:8989";
dynamicConfigOptions = { dynamicConfigOptions = {
http = { http = {
services.sonarr.loadBalancer.servers = [{url = "http://127.0.0.1:8989";}]; # services.sonarr.loadBalancer.servers = [{url = "http://127.0.0.1:8989";}];
routers = { routers = {
sonarr = { sonarr = {
entryPoints = ["websecure"]; entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)"; rule = "Host(`${cfg.url}`)";
service = "sonarr"; service = "sonarr";
tls.certResolver = "letsencrypt"; # tls.certResolver = "letsencrypt";
# middlewares = ["authentik"]; # middlewares = ["authentik"];
}; };
}; };

View File

@@ -1,100 +0,0 @@
{
lib,
config,
pkgs,
self,
...
}: let
inherit (lib) mkEnableOption mkIf types;
cfg = config.server.traefik;
getCloudflareCredentials = hostname:
if hostname == "ziggy"
then config.age.secrets.cloudflareDnsCredentialsZiggy.path
else if hostname == "sobotka"
then config.age.secrets.cloudflareDnsCredentials.path
else throw "Unknown hostname: ${hostname}";
in {
options.server.traefik = {
enable = mkEnableOption "Enable global Traefik reverse proxy with ACME";
};
config = mkIf cfg.enable {
age.secrets.traefikEnv = {
file = "${self}/secrets/traefikEnv.age";
mode = "640";
owner = "root";
group = "traefik";
};
systemd.services.traefik = {
serviceConfig = {
EnvironmentFile = [config.age.secrets.traefikEnv.path];
};
};
networking.firewall.allowedTCPPorts = [80 443];
services = {
tailscale.permitCertUid = "traefik";
traefik = {
enable = true;
staticConfigOptions = {
log = {
level = "DEBUG";
};
tracing = {};
api = {
dashboard = true;
};
certificatesResolvers = {
tailscale.tailscale = {};
letsencrypt = {
acme = {
email = "adam@cnst.dev";
storage = "/var/lib/traefik/cert.json";
dnsChallenge = {
provider = "cloudflare";
resolvers = [
"1.1.1.1:53"
"1.0.0.1:53"
];
};
};
};
};
entryPoints = {
redis = {
address = "0.0.0.0:6381";
};
postgres = {
address = "0.0.0.0:5433";
};
web = {
address = "0.0.0.0:80";
http.redirections.entryPoint = {
to = "websecure";
scheme = "https";
permanent = true;
};
};
websecure = {
address = "0.0.0.0:443";
http.tls = {
certResolver = "letsencrypt";
domains = [
{
main = "cnix.dev";
sans = ["*.cnix.dev"];
}
];
};
};
};
};
};
};
};
}

View File

@@ -2,14 +2,13 @@
{ {
config, config,
lib, lib,
self,
... ...
}: }: let
let
inherit (lib) mkIf mkEnableOption; inherit (lib) mkIf mkEnableOption;
vcfg = config.services.vaultwarden.config; vcfg = config.services.vaultwarden.config;
cfg = config.server.vaultwarden; cfg = config.server.vaultwarden;
in in {
{
options = { options = {
server.vaultwarden = { server.vaultwarden = {
enable = mkEnableOption "Enables vaultwarden"; enable = mkEnableOption "Enables vaultwarden";
@@ -35,6 +34,11 @@ in
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
age.secrets = {
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
};
server = { server = {
fail2ban = lib.mkIf config.server.fail2ban.enable { fail2ban = lib.mkIf config.server.fail2ban.enable {
jails = { jails = {

View File

@@ -2,6 +2,7 @@
lib, lib,
config, config,
pkgs, pkgs,
self,
... ...
}: let }: let
inherit (lib) mkOption mkEnableOption mkIf types; inherit (lib) mkOption mkEnableOption mkIf types;
@@ -16,28 +17,101 @@ in {
default = ""; default = "";
type = types.str; type = types.str;
description = '' description = ''
Public domain name to be used to access the server services via Caddy reverse proxy Public domain name to be used to access the server services via Traefik reverse proxy
'';
};
cloudflared = {
credentialsFile = lib.mkOption {
type = lib.types.str;
example = lib.literalExpression ''
pkgs.writeText "cloudflare-credentials.json" '''
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
'''
'';
};
tunnelId = lib.mkOption {
type = lib.types.str;
example = "00000000-0000-0000-0000-000000000000";
};
};
};
config = mkIf cfg.enable {
age.secrets = {
wwwCloudflared.file = "${self}/secrets/wwwCloudflared.age";
};
server = {
fail2ban = lib.mkIf config.server.www.enable {
jails = {
nginx-404 = {
serviceName = "nginx";
failRegex = ''^.*\[error\].*directory index of.* is forbidden.*client: <HOST>.*$'';
ignoreRegex = "";
maxRetry = 5;
};
};
};
};
services = {
nginx = {
enable = true;
defaultListen = [
{
addr = "127.0.0.1";
port = 8283;
}
];
virtualHosts."webfinger" = {
forceSSL = false;
serverName = cfg.url;
root = "/var/www/webfinger";
locations."= /.well-known/webfinger" = {
root = "/var/www/webfinger";
extraConfig = ''
default_type application/jrd+json;
try_files /.well-known/webfinger =404;
'';
};
locations."= /robots.txt" = {
root = "/var/www/webfinger";
extraConfig = ''
default_type text/plain;
try_files /robots.txt =404;
''; '';
}; };
}; };
config = mkIf cfg.enable { };
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = cfg.url; cloudflared = {
extraConfig = '' enable = true;
handle_path /.well-known/webfinger { tunnels.${cfg.cloudflared.tunnelId} = {
header Content-Type application/jrd+json credentialsFile = cfg.cloudflared.credentialsFile;
respond `{ default = "http_status:404";
ingress."${cfg.url}".service = "http://127.0.0.1:8283";
};
};
};
environment.etc = {
"webfinger/.well-known/webfinger".text = ''
{
"subject": "acct:adam@${cfg.url}", "subject": "acct:adam@${cfg.url}",
"links": [ "links": [
{ {
"rel": "http://openid.net/specs/connect/1.0/issuer", "rel": "http://openid.net/specs/connect/1.0/issuer",
"href": "https://login.${cfg.url}/realms/cnix" "href": "https://auth.${cfg.url}/application/o/tailscale/"
} }
] ]
}`
} }
'';
reverse_proxy http://127.0.0.1:8283 "webfinger/robots.txt".text = ''
User-agent: *
Disallow: /
''; '';
}; };
}; };

View File

@@ -0,0 +1,14 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg 2oTh42u4hxJGAypwwLJwDCPMngauHB8BhKA83xAXr1M
Sr6Hbfnd52F0dUk5RO3wxxJ7RGi3+NUCBq/MzDbKR7s
-> ssh-ed25519 KUYMFA O2j6gYY1QR1ZlFiWw+7y6nKUeE658Wp3PdV6dsMqwTU
NYwnTkZX5PHnNtL1vqJqIsYzIFUY43AVso8ecMAHvWs
-> ssh-ed25519 76RhUQ VTzoQh0fHrG41Gr0YnPY7Jz7yFFugigm/DpUUE/Ny18
SITvKJf5+ql4DhpJoPVvEXdLGIBeKnlLlm8u4QPr0RY
-> ssh-ed25519 Jf8sqw oVI2y3zqpswvyZoNwklrKI1ZbxMJ5a1kzc43RErkbD8
aHNuHMH2XNQ7+9sfsA8LMhBSgTDmvmI1wY26V2j+lsE
--- 0UL0vxM2f5IeVhDO1Cg7SUmhuvpFh+GsEEW4g5JEORU
<EFBFBD>)q<>$*<2A><><EFBFBD>b<10>X<EFBFBD><58><EFBFBD>`<60> %f
_<EFBFBD>%%1ݗ<><DD97><EFBFBD>)<29><>fT<66>٧&<26>`+<2B>K<EFBFBD><4B>q<EFBFBD><71>I<><EEADBE><EFBFBD><EFBFBD><EFBFBD><19><><03>\=<3D>M<EFBFBD><4D><18>
!<21><>7<EFBFBD>b<EFBFBD>]<5D>X<>_lri<72>_<EFBFBD><03><>;<3B>R
<EFBFBD>)<29><>c<EFBFBD>H<><48>5. p<> :m<>_<EFBFBD>&Vj/<2F><01><>Ra|MU<4D><55>b<EFBFBD><62><02>y<EFBFBD><79><EFBFBD><EFBFBD>El<45>nS<6E>9"<11><>گ+<<3C>

Binary file not shown.

View File

@@ -0,0 +1,11 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg dULaZVrpkeN1HqwM+HSU46XJjQznBOxa+wUDSSciK1w
FxqlulfViojLLoskKu56Utiq57rkDC6TocoaFQOgahc
-> ssh-ed25519 KUYMFA QYnb24Av6Vy17Lb5gC6dzQszOxa5bRP2PgFetmqhfCA
MaIes8V0NkyTAzFzbRuCMzMLwhYljYHwhXPKEZEdlC4
-> ssh-ed25519 76RhUQ NLoyNp/z5MXE3Hrmv7CCDYB1X8R1OORm2MZVMbgNDQs
6U8r3wpXNtQdkIH+lo7cDrnjPw9B6eF/jMeb+iW9T1I
-> ssh-ed25519 Jf8sqw GOWsvhSzrHJGJFOgsXr+O1jq7jnjyzKc82Mu7ntrI2Q
P3n32btGFtUxB28/a0iz6lBTM6UP3EYUrq0y8BR49IM
--- geE2uS2TMspihaNwgzH4FQKYoUFFRhjTS6V7F/cdTE0
%<25>^<5E>E3򿈾<33><F2BF88BE><EFBFBD>gg<67><67>ٸk<D9B8><6B>;<3B>lE+b<>x<EFBFBD>Ҝ-<2D>X<>Et'&^<5E>=c<><63>9<EFBFBD>v*<2A>

12
secrets/nginxEnv.age Normal file
View File

@@ -0,0 +1,12 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg SCmn/7gQOD3fRn0PKPXxNBDKNSqUcnejG8tPwjoNT1I
vd57xXCQ16PPPMlNysw6BWSIP/EgB3HrWlesBiQUVA0
-> ssh-ed25519 KUYMFA WVn1OhFDxMMEHFa1yHpBmWskbcRgHyBiDWZjPv8NfX8
8BCp/iUFkRsAGnc+0MEfpRXo1/Xla4WO3qYZMSl7LGw
-> ssh-ed25519 76RhUQ ZfdS1EWtBOwd7+hVnJ/JqxUCDTYmfEs1OwyzXajFMmg
eE0ahMgW76RFu9y9Z+PE6IzaLX3ydhhJvjk5vu2EgXo
-> ssh-ed25519 Jf8sqw Pr/LkT5RQysShzjqEZlXFRHim3WpAav04c/GGftDTiA
TWWRURLPnkpsxxSdSQem9sAoUoLt5wQe0CYl1xl1RaA
--- cfGjcdOvwxLDlANhDe44U5JXGAyRYPZMVtC48PuhLNo
<EFBFBD>Zyr<>#*K<><4B><EFBFBD><EFBFBD> <0B><1F>
$<24><>FB<46>$<24>^<5E>BT<42><54>#D<>v<EFBFBD><76>3<EFBFBD><13><f<>dG$<24><><EFBFBD><~<7E><10><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>m<EFBFBD><6D>8^<1A><><EFBFBD>\# Z<>-8<><38><EFBFBD>D<EFBFBD>dM<64><4D>

View File

@@ -1,7 +1,11 @@
let let
# --- Users --- # --- Users ---
cnst = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEUub8vbzUn2f39ILhAJ2QeH8xxLSjiyUuo8xvHGx/VB adam@cnst.dev"; ukima = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEUub8vbzUn2f39ILhAJ2QeH8xxLSjiyUuo8xvHGx/VB adam@cnst.dev";
kima = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJjoPdpiF8pjKN3ZEHeLEwVxoqwcCdzpVVlZkxJohFdg root@cnix"; rkima = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJjoPdpiF8pjKN3ZEHeLEwVxoqwcCdzpVVlZkxJohFdg root@cnix";
# --- Hosts: bunk ---
ubunk = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXCjkKouZrsMoswMIeueO8X/c3kuY3Gb0E9emvkqwUv cnst@cnixpad";
rbunk = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH72llEVDSHH/FZnjLVCe6zfdkdJRRVg2QL+ifHiPXXk root@cnix";
# --- Hosts: sobotka --- # --- Hosts: sobotka ---
usobotka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG5ydTeaWcowmNXdDNqIa/lb5l9w5CAzyF2Kg6U5PSSu cnst@sobotka"; usobotka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG5ydTeaWcowmNXdDNqIa/lb5l9w5CAzyF2Kg6U5PSSu cnst@sobotka";
@@ -12,9 +16,13 @@ let
rziggy = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHnca8xg1MZ4Hx5k5SVFSxcPnWc1O6r7w7JGYzX9aQm8 root@nixos"; rziggy = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHnca8xg1MZ4Hx5k5SVFSxcPnWc1O6r7w7JGYzX9aQm8 root@nixos";
# --- Groups --- # --- Groups ---
core = [ kima = [
cnst ukima
kima rkima
];
bunk = [
ubunk
rbunk
]; ];
sobotka = [ sobotka = [
usobotka usobotka
@@ -24,38 +32,41 @@ let
uziggy uziggy
rziggy rziggy
]; ];
all = core ++ sobotka ++ ziggy; all = kima ++ bunk ++ sobotka ++ ziggy;
in { in {
# Generic # Generic
"cnstssh.age".publicKeys = core; "cnstssh.age".publicKeys = kima;
"cnixssh.age".publicKeys = core; "cnixssh.age".publicKeys = kima;
"certpem.age".publicKeys = core; "certpem.age".publicKeys = kima;
"keypem.age".publicKeys = core; "keypem.age".publicKeys = kima;
"mailpwd.age".publicKeys = core; "mailpwd.age".publicKeys = kima;
"gcapi.age".publicKeys = core; "gcapi.age".publicKeys = kima;
# Shared between core + sobotka # Shared between kima + sobotka
"cloudflareEnvironment.age".publicKeys = core ++ sobotka; "cloudflareEnvironment.age".publicKeys = kima ++ sobotka;
"vaultwardenEnvironment.age".publicKeys = core ++ sobotka; "vaultwardenEnvironment.age".publicKeys = kima ++ sobotka;
"homepageEnvironment.age".publicKeys = core ++ sobotka; "homepageEnvironment.age".publicKeys = kima ++ sobotka;
"cloudflareFirewallApiKey.age".publicKeys = core ++ sobotka; "cloudflareFirewallApiKey.age".publicKeys = kima ++ sobotka;
"vaultwardenCloudflared.age".publicKeys = core ++ sobotka; "vaultwardenCloudflared.age".publicKeys = kima ++ sobotka;
"nextcloudCloudflared.age".publicKeys = core ++ sobotka; "nextcloudCloudflared.age".publicKeys = kima ++ sobotka;
"nextcloudAdminPass.age".publicKeys = core ++ sobotka; "nextcloudAdminPass.age".publicKeys = kima ++ sobotka;
"cloudflareDnsApiToken.age".publicKeys = core ++ sobotka; "cloudflareDnsApiToken.age".publicKeys = kima ++ sobotka;
"cloudflareDnsCredentials.age".publicKeys = core ++ sobotka; "cloudflareDnsCredentials.age".publicKeys = kima ++ sobotka;
"wgCredentials.age".publicKeys = core ++ sobotka; "wgCredentials.age".publicKeys = kima ++ sobotka;
"wgSobotkaPrivateKey.age".publicKeys = core ++ sobotka; "wgSobotkaPrivateKey.age".publicKeys = kima ++ sobotka;
"gluetunEnvironment.age".publicKeys = core ++ sobotka; "gluetunEnvironment.age".publicKeys = kima ++ sobotka;
"pihole.age".publicKeys = core ++ sobotka; "sobotkaPihole.age".publicKeys = kima ++ sobotka;
"slskd.age".publicKeys = core ++ sobotka; "slskd.age".publicKeys = kima ++ sobotka;
"authentikEnv.age".publicKeys = core ++ sobotka; "authentikEnv.age".publicKeys = kima ++ sobotka;
"traefikEnv.age".publicKeys = core ++ sobotka; "nginxEnv.age".publicKeys = kima ++ sobotka;
"wwwCloudflared.age".publicKeys = kima ++ sobotka;
"authentikCloudflared.age".publicKeys = kima ++ sobotka;
"jellyfinCloudflared.age".publicKeys = kima ++ sobotka;
# Ziggy-specific # Ziggy-specific
"cloudflareDnsCredentialsZiggy.age".publicKeys = core ++ ziggy; "cloudflareDnsCredentialsZiggy.age".publicKeys = kima ++ ziggy;
"piholeZiggy.age".publicKeys = core ++ ziggy; "ziggyPihole.age".publicKeys = kima ++ ziggy;
# Both sobotka + ziggy (for HA stuff like keepalived) # Both sobotka + ziggy (for HA stuff like keepalived)
"keepalived.age".publicKeys = core ++ sobotka ++ ziggy; "keepalived.age".publicKeys = kima ++ sobotka ++ ziggy;
} }

Binary file not shown.

View File

@@ -0,0 +1,11 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg CWarcJM8RPjJW+e3BQ99KEUnOZQUDEIIeygeh/8MZUw
xux60KMmyOVvgiuEqyEPXM1Wr2ne8AyHT6CAWKMOcKo
-> ssh-ed25519 KUYMFA AThOlxHT41vsczkSGzJmT+VmWC2dAnLiIcTJP+YySkc
Jy8HyRuzIFtGYMimxsQNm2NnbluVwS6ZuXhq4uRfabY
-> ssh-ed25519 76RhUQ dKyDJ4DCNtYWQ2+cC7gwa+14aw99S+mU38tpQrlOmFc
0mD5Qcv8b8Bh1e4mbqdH26UtCJaUe7C7dDDSXJd1iRY
-> ssh-ed25519 Jf8sqw To2I/347gMqYx0PxMgYqbGekUpfqWOQwtgJ+0AFilTw
nIo4dH9JnOuWo48a17Kjyee5sQV8HN+PNXCWDT4fjIg
--- SuE6Z9ipbuWhxoaULMf6OGtG3BNkQ1BpWXkgfAI7Y6Y
<EFBFBD>R<EFBFBD>u1<12><><16><><EFBFBD>d<EFBFBD>ژdʋ(s <0B>)<29>M0v<30>ѹ<EFBFBD><D1B9><EFBFBD>Z<EFBFBD>V<EFBFBD><56><10>q<05>i<EFBFBD>i<EFBFBD><69>Ec* <09>{<7B>~teP<65><50><EFBFBD>{<1C>D<>mA~Ŭ<><1B>c.<2E>TbƝ<62>}<<3C><><EFBFBD><EFBFBD><EFBFBD>e0<65>Vq <0C><><EFBFBD>k<EFBFBD><6B><EFBFBD> b<>T<1F><>*Y<><59>$<24><>t<EFBFBD><74>:<3A><>^<1C><>+<2B><1D><>;<3B>1<EFBFBD><31><EFBFBD>ۤ<EFBFBD><DBA4>Ӎ<12>X<EFBFBD>H<EFBFBD><03><>u<EFBFBD><75><EFBFBD>g<EFBFBD>߄<EFBFBD>o<EFBFBD>/<2F>G<EFBFBD><0E><><16>Kl<4B>I<EFBFBD>C<EFBFBD><43>==A<><11><>Y<EFBFBD><59><EFBFBD>U<EFBFBD><55><EFBFBD><EFBFBD>

View File

@@ -23,6 +23,5 @@
json.enable = false; json.enable = false;
manpages.enable = false; manpages.enable = false;
}; };
programs.home-manager.enable = true; programs.home-manager.enable = true;
} }

View File

@@ -131,7 +131,7 @@
enable = true; enable = true;
}; };
syncthing = { syncthing = {
enable = true; enable = false;
}; };
udiskie = { udiskie = {
enable = true; enable = true;

View File

@@ -132,7 +132,7 @@
enable = true; enable = true;
}; };
syncthing = { syncthing = {
enable = true; enable = false;
}; };
udiskie = { udiskie = {
enable = true; enable = true;

View File

@@ -1,154 +0,0 @@
{
home = {
programs = {
aerc = {
enable = false;
};
alacritty = {
enable = false;
};
bash = {
enable = true;
};
chromium = {
enable = false;
};
discord = {
enable = false;
};
eza = {
enable = true;
};
floorp = {
enable = false;
};
firefox = {
enable = false;
};
fish = {
enable = true;
};
foot = {
enable = false;
};
fuzzel = {
enable = false;
};
git = {
enable = true;
};
ghostty = {
enable = false;
};
helix = {
enable = true;
};
hyprlock = {
enable = false;
};
jujutsu = {
enable = false;
};
kitty = {
enable = false;
};
mpv = {
enable = false;
};
neovim = {
enable = false;
};
nvf = {
enable = false;
};
nwg-bar = {
enable = false;
};
pkgs = {
enable = true;
};
rofi = {
enable = false;
};
ssh = {
enable = true;
};
tuirun = {
enable = false;
};
vscode = {
enable = false;
};
waybar = {
enable = false;
};
wezterm = {
enable = false;
};
yazi = {
enable = false;
};
zathura = {
enable = false;
};
zed-editor = {
enable = false;
};
zellij = {
enable = false;
};
zen = {
enable = false;
};
zsh = {
enable = false;
};
};
services = {
blueman-applet = {
enable = false;
};
copyq = {
enable = false;
};
dconf = {
settings = {
color-scheme = "prefer-dark";
};
};
dunst = {
enable = false;
};
gpg = {
enable = true;
};
gtk = {
enable = false;
};
hypridle = {
enable = false;
};
hyprpaper = {
enable = false;
};
mako = {
enable = false;
};
nix-index = {
enable = true;
};
protonmail-bridge = {
enable = false;
};
syncthing = {
enable = false;
};
udiskie = {
enable = false;
};
xdg = {
enable = false;
};
};
};
}

View File

@@ -14,8 +14,8 @@ let
BROWSER = "zen"; BROWSER = "zen";
EDITOR = "hx"; EDITOR = "hx";
TERM = "xterm-256color"; TERM = "xterm-256color";
VK_ICD_FILENAMES = "/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json"; # VK_ICD_FILENAMES = "/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json";
STEAM_EXTRA_COMPAT_TOOLS_PATHS = "/home/cnst/.steam/root/compatibilitytools.d"; # STEAM_EXTRA_COMPAT_TOOLS_PATHS = "/home/cnst/.steam/root/compatibilitytools.d";
QT_QPA_PLATFORM = "wayland"; QT_QPA_PLATFORM = "wayland";
XDG_SESSION_TYPE = "wayland"; XDG_SESSION_TYPE = "wayland";
}; };