1 Commits

Author SHA1 Message Date
123dfd7605 all the broken 2025-10-04 20:35:06 +02:00
35 changed files with 561 additions and 633 deletions

190
flake.lock generated
View File

@@ -29,11 +29,11 @@
"systems": "systems_2" "systems": "systems_2"
}, },
"locked": { "locked": {
"lastModified": 1760083914, "lastModified": 1758874004,
"narHash": "sha256-I9IMO9d+z71oeqOz6gOre07tK2Du3vp2FcOW3x4FDXw=", "narHash": "sha256-+RUCBtT01Z595NpGc6Tvms+dJ/C/cn1zdjT9+gE6dbU=",
"owner": "anyrun-org", "owner": "anyrun-org",
"repo": "anyrun", "repo": "anyrun",
"rev": "3050aa30e25957bbb9e1ac91a44d3979eccadf59", "rev": "3c571bc1514c4211d1d6c011a1d482f97efd9c5f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -83,11 +83,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759499898, "lastModified": 1755946532,
"narHash": "sha256-UNzYHLWfkSzLHDep5Ckb5tXc0fdxwPIrT+MY4kpQttM=", "narHash": "sha256-POePremlUY5GyA1zfbtic6XLxDaQcqHN6l+bIxdT5gc=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "aquamarine", "repo": "aquamarine",
"rev": "655e067f96fd44b3f5685e17f566b0e4d535d798", "rev": "81584dae2df6ac79f6b6dae0ecb7705e95129ada",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -153,11 +153,11 @@
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1760148209, "lastModified": 1759348172,
"narHash": "sha256-ssMUeLk1cmLqzNMW6l9dgGoLtOY9F9dEGplJlWJmNis=", "narHash": "sha256-ZPUJX2ZA0ndcHndIA/S/nRESIJV0rifPr91SUpzJtEM=",
"owner": "chaotic-cx", "owner": "chaotic-cx",
"repo": "nyx", "repo": "nyx",
"rev": "b51bb724939dbfa264f08522efffce2bb47b6135", "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": 1760164678, "lastModified": 1759473677,
"narHash": "sha256-yxcfwZCysR6zPaFv7is3/FWd1h0h6kXME0vueSwTBhU=", "narHash": "sha256-9AFDP5AhXe06aXXPsV7bDGH7KA9Wo4uUtK7pRrsxuFQ=",
"owner": "nix-community", "owner": "nix-community",
"repo": "fenix", "repo": "fenix",
"rev": "2579f163559b902959cc420a6d3bfbd98c46a323", "rev": "8532b07ced6a95d57650124c79534a3c770431ab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -491,11 +491,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759523803, "lastModified": 1758108966,
"narHash": "sha256-PTod9NG+i3XbbnBKMl/e5uHDBYpwIWivQ3gOWSEuIEM=", "narHash": "sha256-ytw7ROXaWZ7OfwHrQ9xvjpUWeGVm86pwnEd1QhzawIo=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "cfc9f7bb163ad8542029d303e599c0f7eee09835", "rev": "54df955a695a84cd47d4a43e08e1feaf90b1fd9b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -571,11 +571,11 @@
}, },
"hardware": { "hardware": {
"locked": { "locked": {
"lastModified": 1760106635, "lastModified": 1759261527,
"narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=", "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=",
"owner": "nixos", "owner": "nixos",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903", "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": 1759850138, "lastModified": 1759201995,
"narHash": "sha256-fYHIxjTvVIAEDWzenUROuzDPxy1rBCXZNPgh4b1dfgo=", "narHash": "sha256-3STv6fITv8Ar/kl0H7vIA7VV0d2gyLh8UL0BOiVacXg=",
"owner": "helix-editor", "owner": "helix-editor",
"repo": "helix", "repo": "helix",
"rev": "5b0563419eeeaf0595c848865c46be4abad246a7", "rev": "bfcbef10c513108c7b43317569416c2eefc4ed44",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -610,11 +610,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760130406, "lastModified": 1759337100,
"narHash": "sha256-GKMwBaFRw/C1p1VtjDz4DyhyzjKUWyi1K50bh8lgA2E=", "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "d305eece827a3fe317a2d70138f53feccaf890a1", "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -652,11 +652,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760061988, "lastModified": 1759261733,
"narHash": "sha256-CeuMo7fjWm3XaoK+b1PGyaVIlE1GHudoxk9jrJFvfbY=", "narHash": "sha256-G104PUPKBgJmcu4NWs0LUaPpSOTD4jiq4mamLWu3Oc0=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "c7f4214faca2f196c551b767c12a70bfa0614510", "rev": "5a21f4819ee1be645f46d6b255d49f4271ef6723",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -710,11 +710,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759490292, "lastModified": 1758192433,
"narHash": "sha256-T6iWzDOXp8Wv0KQOCTHpBcmAOdHJ6zc/l9xaztW6Ivc=", "narHash": "sha256-CR6RnqEJSTiFgA6KQY4TTLUWbZ8RBnb+hxQqesuQNzQ=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprgraphics", "repo": "hyprgraphics",
"rev": "9431db625cd9bb66ac55525479dce694101d6d7a", "rev": "c44e749dd611521dee940d00f7c444ee0ae4cfb7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -739,11 +739,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759490292, "lastModified": 1750621377,
"narHash": "sha256-T6iWzDOXp8Wv0KQOCTHpBcmAOdHJ6zc/l9xaztW6Ivc=", "narHash": "sha256-8u6b5oAdX0rCuoR8wFenajBRmI+mzbpNig6hSCuWUzE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprgraphics", "repo": "hyprgraphics",
"rev": "9431db625cd9bb66ac55525479dce694101d6d7a", "rev": "b3d628d01693fb9bb0a6690cd4e7b80abda04310",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -803,11 +803,11 @@
"xdph": "xdph" "xdph": "xdph"
}, },
"locked": { "locked": {
"lastModified": 1760143218, "lastModified": 1759399554,
"narHash": "sha256-OhJPROcRcwBkjOKkXr/f3/7wuSjhAIqr8WfmEUF9Uuo=", "narHash": "sha256-FsFugHj7He5siEcmoRUdMKHB8uMzyneK/fynPS57W4E=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland", "repo": "hyprland",
"rev": "d599513d4a72d66ac62ffdedc41d6653fa81b39e", "rev": "3bcfa94ee4189faaa4daf661949e88cf28c00d94",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -824,11 +824,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759613406, "lastModified": 1759238633,
"narHash": "sha256-PzgQJydp+RlKvwDi807pXPlURdIAVqLppZDga3DwPqg=", "narHash": "sha256-4/AtRCQKXuU49ozZZouWuC+T7vCjQh9HAz3N8Tt5OZE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "contrib", "repo": "contrib",
"rev": "32e1a75b65553daefb419f0906ce19e04815aa3a", "rev": "513d71d3f42c05d6a38e215382c5a6ce971bd77d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -942,11 +942,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759080228, "lastModified": 1757694755,
"narHash": "sha256-RgDoAja0T1hnF0pTc56xPfLfFOO8Utol2iITwYbUhTk=", "narHash": "sha256-j+w5QUUr2QT/jkxgVKecGYV8J7fpzXCMgzEEr6LG9ug=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-qtutils", "repo": "hyprland-qtutils",
"rev": "629b15c19fa4082e4ce6be09fdb89e8c3312aed7", "rev": "5ffdfc13ed03df1dae5084468d935f0a3f2c9a4c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -971,11 +971,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758927902, "lastModified": 1756810301,
"narHash": "sha256-LZgMds7M94+vuMql2bERQ6LiFFdhgsEFezE4Vn+Ys3A=", "narHash": "sha256-wgZ3VW4VVtjK5dr0EiK9zKdJ/SOqGIBXVG85C3LVxQA=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlang", "repo": "hyprlang",
"rev": "4dafa28d4f79877d67a7d1a654cddccf8ebf15da", "rev": "3d63fb4a42c819f198deabd18c0c2c1ded1de931",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1006,11 +1006,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760023949, "lastModified": 1759492718,
"narHash": "sha256-fu0B4duamVdbkPio/czu1XhsPLRXUJpZLDrSk3nih4U=", "narHash": "sha256-Mxi/LyyHE9VKUnBs4y1hXO+wRqukZJjbx/igqKQxkQk=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlock", "repo": "hyprlock",
"rev": "36ec73f166d9434a3f27c96c575198906f77644a", "rev": "3cb799b1842016c85cca2db66fa502b8179cf0fe",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1044,11 +1044,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760120448, "lastModified": 1754481642,
"narHash": "sha256-l/OxM4q/nLVv47OuS4bG2J7k0m+G7/3AMtvrV64XLb0=", "narHash": "sha256-e1phd6KwtUsS9C2ShD+fQvfk2Dgr2JQi+rTDQUW15iE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprpaper", "repo": "hyprpaper",
"rev": "1733e0025b194c9bc083f4cd8782c5f151858a58", "rev": "bcb1ffa322369c4898347ab5a7399a3d18494c8f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1069,11 +1069,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759619523, "lastModified": 1756117388,
"narHash": "sha256-r1ed7AR2ZEb2U8gy321/Xcp1ho2tzn+gG1te/Wxsj1A=", "narHash": "sha256-oRDel6pNl/T2tI+nc/USU9ZP9w08dxtl7hiZxa0C/Wc=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprutils", "repo": "hyprutils",
"rev": "3df7bde01efb3a3e8e678d1155f2aa3f19e177ef", "rev": "b2ae3204845f5f2f79b4703b441252d8ad2ecfd0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1144,11 +1144,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1755184602, "lastModified": 1750371869,
"narHash": "sha256-RCBQN8xuADB0LEgaKbfRqwm6CdyopE1xIEhNc67FAbw=", "narHash": "sha256-lGk4gLjgZQ/rndUkzmPYcgbHr8gKU5u71vyrjnwfpB4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprwayland-scanner", "repo": "hyprwayland-scanner",
"rev": "b3b0f1f40ae09d4447c20608e5a4faf8bf3c492d", "rev": "aa38edd6e3e277ae6a97ea83a69261a5c3aab9fd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1191,11 +1191,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759815224, "lastModified": 1759217228,
"narHash": "sha256-HbdOyjqHm38j6o5mV24i0bn+r5ykS+VJBnWJuZ0fE+A=", "narHash": "sha256-P13ExJlhMVkrc5LxZLNkIJZhjNYo3LLXnxDsUNrdnMQ=",
"owner": "Jovian-Experiments", "owner": "Jovian-Experiments",
"repo": "Jovian-NixOS", "repo": "Jovian-NixOS",
"rev": "ee974f496a080c61b3164992c850f43741edcc52", "rev": "e52c15ab25f7dc68dde527c8df5bfa9d80d8e64f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1278,11 +1278,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760146997, "lastModified": 1759455985,
"narHash": "sha256-x2sF8Q4tWz3DI166s+KFDXySrK+cN+/YEd3DfhnhBLQ=", "narHash": "sha256-8qDv7NXH3fj1CDXed7c7vJLtrRKDZSo0x6TaWSfelVg=",
"owner": "fufexan", "owner": "fufexan",
"repo": "nix-gaming", "repo": "nix-gaming",
"rev": "ad505387568d024654da88fef03d9c5319cba92f", "rev": "eb5ab503cbd3cb386e8d85a55a9faed73ec7dc37",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1363,11 +1363,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1760038930, "lastModified": 1759147044,
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=", "narHash": "sha256-3ZPFytJOcLjTChljeaGgoaNj+tOqzgEpqZAvRe3bU90=",
"owner": "NixOS", "owner": "PedroHLC",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3", "rev": "18e83bbe13aa50992777832b52bd0e0d8585fb3b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1395,11 +1395,11 @@
}, },
"nixpkgs_5": { "nixpkgs_5": {
"locked": { "locked": {
"lastModified": 1759381078, "lastModified": 1740560979,
"narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", "narHash": "sha256-Vr3Qi346M+8CjedtbyUevIGDZW8LcA1fTG0ugPY/Hic=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", "rev": "5135c59491985879812717f4c9fea69604e7f26f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1411,11 +1411,11 @@
}, },
"nixpkgs_6": { "nixpkgs_6": {
"locked": { "locked": {
"lastModified": 1759381078, "lastModified": 1758198701,
"narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", "narHash": "sha256-7To75JlpekfUmdkUZewnT6MoBANS0XVypW6kjUOXQwc=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", "rev": "0147c2f1d54b30b5dd6d4a8c8542e8d7edf93b5d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1443,11 +1443,11 @@
}, },
"nixpkgs_8": { "nixpkgs_8": {
"locked": { "locked": {
"lastModified": 1760038930, "lastModified": 1759381078,
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=", "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3", "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1482,11 +1482,11 @@
"systems": "systems_5" "systems": "systems_5"
}, },
"locked": { "locked": {
"lastModified": 1760153667, "lastModified": 1759469269,
"narHash": "sha256-F7KmXT/Izse6Q6CkD5GCImoGPaDJxl03Kd7eD+eY/bU=", "narHash": "sha256-DP833ejGUNRRHsJOB3WRTaWWXLNucaDga2ju/fGe+sc=",
"owner": "notashelf", "owner": "notashelf",
"repo": "nvf", "repo": "nvf",
"rev": "9df9d51fd9fc8f9a8fc377f984ea3b7ae796172d", "rev": "e48638aef3a95377689de0ef940443c64f870a09",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1626,11 +1626,11 @@
"rust-analyzer-src": { "rust-analyzer-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1760090851, "lastModified": 1759301569,
"narHash": "sha256-XGkBjf4Dzg6tXd0KGgKzeW4oVX/iLzLhD3rQ1cATpqM=", "narHash": "sha256-7StxDed3v2fAWLkl+Hse9FlpjT7Dk7Cn/4vxTFyEhIg=",
"owner": "rust-lang", "owner": "rust-lang",
"repo": "rust-analyzer", "repo": "rust-analyzer",
"rev": "b93180b4f2cb3c81ac7f17f46e3dfcb30ecc7843", "rev": "472037b789cf593172d6adf3b8d9f7a429f6cd9b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1648,11 +1648,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760063676, "lastModified": 1759286284,
"narHash": "sha256-s5Fjh43skH2L+avOGioLmEHoYZffDbg3abV5h0gjeew=", "narHash": "sha256-JLdGGc4XDutzSD1L65Ni6Ye+oTm8kWfm0KTPMcyl7Y4=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "897deed0923cc5a1d560c5176abe0d172ec9716d", "rev": "f6f2da475176bb7cff51faae8b3fe879cd393545",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1669,11 +1669,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759631821, "lastModified": 1740623427,
"narHash": "sha256-V8A1L0FaU/aSXZ1QNJScxC12uP4hANeRBgI4YdhHeRM=", "narHash": "sha256-3SdPQrZoa4odlScFDUHd4CUPQ/R1gtH4Mq9u8CBiK8M=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "1d7cbdaad90f8a5255a89a6eddd8af24dc89cafe", "rev": "d342e8b5fd88421ff982f383c853f0fc78a847ab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1815,11 +1815,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760120816, "lastModified": 1758728421,
"narHash": "sha256-gq9rdocpmRZCwLS5vsHozwB6b5nrOBDNc2kkEaTXHfg=", "narHash": "sha256-ySNJ008muQAds2JemiyrWYbwbG+V7S5wg3ZVKGHSFu8=",
"owner": "numtide", "owner": "numtide",
"repo": "treefmt-nix", "repo": "treefmt-nix",
"rev": "761ae7aff00907b607125b2f57338b74177697ed", "rev": "5eda4ee8121f97b218f7cc73f5172098d458f1d1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1923,11 +1923,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759969704, "lastModified": 1759180079,
"narHash": "sha256-T7f/invcFIKHrBqD+FLf/C/HOGmpYfbZUzTDxFscpOA=", "narHash": "sha256-5hqTGqAKcLEumY3tqOtHK17CA6RkzS1I0EGKfuoyb58=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "1173c777dc8daddcc4959260a7b00fd8abc884c5", "rev": "d4a254b38c7ac2b99931220d767610adfa3a57fe",
"revCount": 137, "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

@@ -29,13 +29,6 @@
}; };
network = { network = {
enable = true; enable = true;
nameservers = [
"192.168.88.1"
"192.168.88.69"
];
search = [
"taila7448a.ts.net"
];
interfaces = { interfaces = {
"eno1" = { "eno1" = {
allowedTCPPorts = [ allowedTCPPorts = [
@@ -73,7 +66,7 @@
}; };
}; };
gamescope = { gamescope = {
enable = false; enable = true;
}; };
gimp = { gimp = {
enable = true; enable = true;

View File

@@ -68,10 +68,7 @@ in {
boot = { boot = {
supportedFilesystems = ["zfs"]; supportedFilesystems = ["zfs"];
zfs = { zfs.extraPools = ["data"];
package = pkgs.zfs_unstable;
extraPools = ["data"];
};
}; };
services.zfs = { services.zfs = {

View File

@@ -109,7 +109,7 @@
enable = true; enable = true;
}; };
dev = { dev = {
enable = true; enable = false;
}; };
}; };
mysql-workbench = { mysql-workbench = {

View File

@@ -8,10 +8,10 @@
uid = 994; uid = 994;
gid = 993; gid = 993;
traefik = { nginx = {
enable = true; enable = true;
}; };
tailscale = { gitea = {
enable = true; enable = true;
}; };
unbound = { unbound = {
@@ -42,19 +42,15 @@
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;
}; };
gitea = {
enable = true;
url = "git.cnst.dev";
cloudflared = {
tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
credentialsFile = config.age.secrets.giteaCloudflared.path;
};
};
vaultwarden = { vaultwarden = {
enable = true; enable = true;
url = "vault.cnst.dev"; url = "vault.cnst.dev";
@@ -64,7 +60,7 @@
}; };
}; };
www = { www = {
enable = true; enable = false;
url = "cnst.dev"; url = "cnst.dev";
cloudflared = { cloudflared = {
tunnelId = "e5076186-efb7-405a-998c-6155af7fb221"; tunnelId = "e5076186-efb7-405a-998c-6155af7fb221";
@@ -96,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

@@ -141,10 +141,9 @@
./server/keepalived ./server/keepalived
./server/gitea ./server/gitea
./server/postgres ./server/postgres
./server/traefik ./server/nginx
./server/www ./server/www
./server/authentik ./server/authentik
./server/tailscale
]; ];
}; };
settings = { settings = {

View File

@@ -88,7 +88,7 @@ in
hyprpicker hyprpicker
libnotify libnotify
pamixer pamixer
loupe oculante
adwaita-icon-theme adwaita-icon-theme
qt5.qtwayland qt5.qtwayland
qt6.qtwayland qt6.qtwayland

View File

@@ -84,15 +84,15 @@ in
"application/pdf" = "org.pwmt.zathura-pdf-mupdf.desktop"; "application/pdf" = "org.pwmt.zathura-pdf-mupdf.desktop";
"inode/directory" = "thunar.desktop"; "inode/directory" = "thunar.desktop";
"image/apng" = "feh.desktop"; "image/apng" = "oculante.desktop";
"image/avif" = "feh.desktop"; "image/avif" = "oculante.desktop";
"image/bmp" = "feh.desktop"; "image/bmp" = "oculante.desktop";
"image/gif" = "feh.desktop"; "image/gif" = "oculante.desktop";
"image/jpeg" = "feh.desktop"; "image/jpeg" = "oculante.desktop";
"image/png" = "feh.desktop"; "image/png" = "oculante.desktop";
"image/svg+xml" = "feh.desktop"; "image/svg+xml" = "oculante.desktop";
"image/tiff" = "feh.desktop"; "image/tiff" = "oculante.desktop";
"image/webp" = "feh.desktop"; "image/webp" = "oculante.desktop";
"video/H264" = [ "video/H264" = [
"mpv.desktop" "mpv.desktop"

View File

@@ -2,47 +2,38 @@
config, config,
lib, lib,
... ...
}: let }:
inherit let
(lib) inherit (lib)
mkIf mkIf
mkEnableOption mkEnableOption
mkOption mkOption
types types
; ;
cfg = config.nixos.hardware.network; cfg = config.nixos.hardware.network;
in { in
{
options = { options = {
nixos.hardware.network = { nixos.hardware.network = {
enable = mkEnableOption "Enable the custom networking module"; enable = mkEnableOption "Enable the custom networking module";
nameservers = mkOption {
type = types.listOf types.str;
default = [];
description = "The list of nameservers ";
};
search = mkOption {
type = types.listOf types.str;
default = [];
description = "Domain search paths";
};
interfaces = mkOption { interfaces = mkOption {
type = types.attrsOf ( type = types.attrsOf (
types.submodule { types.submodule {
options = { options = {
allowedTCPPorts = mkOption { allowedTCPPorts = mkOption {
type = types.listOf types.int; type = types.listOf types.int;
default = []; default = [ ];
description = "List of allowed TCP ports for this interface."; description = "List of allowed TCP ports for this interface.";
}; };
allowedUDPPorts = mkOption { allowedUDPPorts = mkOption {
type = types.listOf types.int; type = types.listOf types.int;
default = []; default = [ ];
description = "List of allowed UDP ports for this interface."; description = "List of allowed UDP ports for this interface.";
}; };
}; };
} }
); );
default = {}; default = { };
description = "Network interface configurations."; description = "Network interface configurations.";
}; };
extraHosts = mkOption { extraHosts = mkOption {
@@ -56,7 +47,7 @@ in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
assertions = [ assertions = [
{ {
assertion = cfg.interfaces != {} -> config.networking.networkmanager.enable; assertion = cfg.interfaces != { } -> config.networking.networkmanager.enable;
message = "Network interfaces configured but NetworkManager is not enabled"; message = "Network interfaces configured but NetworkManager is not enabled";
} }
]; ];
@@ -64,8 +55,6 @@ in {
networking = { networking = {
networkmanager.enable = true; networkmanager.enable = true;
nftables.enable = true; nftables.enable = true;
nameservers = cfg.nameservers;
search = cfg.search;
firewall = { firewall = {
enable = true; enable = true;
inherit (cfg) interfaces; inherit (cfg) interfaces;
@@ -74,8 +63,8 @@ in {
}; };
systemd.services.NetworkManager = { systemd.services.NetworkManager = {
wants = ["nftables.service"]; wants = [ "nftables.service" ];
after = ["nftables.service"]; after = [ "nftables.service" ];
}; };
}; };
} }

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
@@ -78,7 +76,6 @@ in
openssl openssl
xmrig xmrig
ocl-icd ocl-icd
dig
] ]
(mkIf cfg.common.enable [ (mkIf cfg.common.enable [
@@ -97,6 +94,9 @@ in
]) ])
(mkIf cfg.desktop.enable [ (mkIf cfg.desktop.enable [
protonup
winetricks
wine
geekbench geekbench
unigine-heaven unigine-heaven
]) ])
@@ -107,13 +107,17 @@ in
(mkIf cfg.server.enable [ (mkIf cfg.server.enable [
nvtopPackages.intel nvtopPackages.intel
nvtopPackages.amd
dig
helix helix
zfs
zfstools zfstools
cron
acme-sh
]) ])
(mkIf cfg.dev.enable [ (mkIf cfg.dev.enable [
# lldb_20 # some biuld error atm # lldb_20 # some biuld error atm
sqlite
gemini-cli gemini-cli
nfs-utils nfs-utils
gcc gcc
@@ -140,6 +144,7 @@ in
prettierd prettierd
# php84Packages.php-cs-fixer # php84Packages.php-cs-fixer
shfmt shfmt
luaformatter
black black
]) ])
]; ];

View File

@@ -1,7 +1,6 @@
{ {
config, config,
lib, lib,
pkgs,
... ...
}: }:
let let
@@ -18,20 +17,6 @@ in
enable = true; enable = true;
gamescopeSession.enable = true; gamescopeSession.enable = true;
}; };
gamescope = {
enable = true;
capSysNice = true;
args = [
"--rt"
"--expose-wayland"
];
};
}; };
environment.systemPackages = with pkgs; [
protonup
wine
winetricks
wine-wayland
];
}; };
} }

View File

@@ -70,7 +70,7 @@ 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";

View File

@@ -45,6 +45,7 @@ in
# nodePackages_latest.sql-formatter # nodePackages_latest.sql-formatter
prettierd prettierd
shfmt shfmt
luaformatter
black black
]; ];
}; };

View File

@@ -64,7 +64,7 @@ in {
jails = { jails = {
authentik = { authentik = {
serviceName = "authentik"; serviceName = "authentik";
failRegex = ''^.*Username or password is incorrect.*IP:\s*<HOST>''; failRegex = "^.*Username or password is incorrect.*IP:\s*<HOST>";
}; };
}; };
}; };
@@ -97,21 +97,16 @@ in {
middlewares = { middlewares = {
authentik = { authentik = {
forwardAuth = { forwardAuth = {
# 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";
}; };
}; };
}; };
@@ -127,7 +122,7 @@ in {
routers = { routers = {
auth = { auth = {
entryPoints = ["websecure"]; entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`) && 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

@@ -30,28 +30,14 @@ in {
example = "vaultwarden"; example = "vaultwarden";
type = lib.types.str; type = lib.types.str;
}; };
_groupsre = lib.mkOption {
type = lib.types.lines;
example = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
default = "";
};
failRegex = lib.mkOption { failRegex = lib.mkOption {
type = lib.types.lines; type = lib.types.str;
example = '' example = "Login failed from IP: <HOST>";
^Login failed from IP: <HOST>$
^Two-factor challenge failed from <HOST>$
'';
}; };
ignoreRegex = lib.mkOption { ignoreRegex = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = ""; default = "";
}; };
datePattern = lib.mkOption {
type = lib.types.str;
default = "";
example = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
description = "Optional datepattern line for the fail2ban filter.";
};
maxRetry = lib.mkOption { maxRetry = lib.mkOption {
type = lib.types.int; type = lib.types.int;
default = 3; default = 3;
@@ -72,14 +58,14 @@ in {
jails = jails =
lib.attrsets.mapAttrs (name: value: { lib.attrsets.mapAttrs (name: value: {
settings = { settings = {
bantime = "24h"; bantime = "168h";
findtime = "10m"; 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";
}; };
}) })
@@ -89,18 +75,11 @@ in {
environment.etc = lib.attrsets.mergeAttrsList [ environment.etc = lib.attrsets.mergeAttrsList [
(lib.attrsets.mapAttrs' ( (lib.attrsets.mapAttrs' (
name: value: (lib.nameValuePair "fail2ban/filter.d/${name}.conf" { name: value: (lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
text = text = ''
'' [Definition]
[Definition] failregex = ${value.failRegex}
failregex = ${value.failRegex} ignoreregex = ${value.ignoreRegex}
ignoreregex = ${value.ignoreRegex} '';
''
+ lib.optionalString (value.datePattern != "") ''
datepattern = ${value.datePattern}
''
+ lib.optionalString (value._groupsre != "") ''
_groupsre = ${value._groupsre}
'';
}) })
) )
cfg.jails) cfg.jails)

View File

@@ -1,8 +1,7 @@
# "inspired" by @jtojnar <3 # taken from @jtojnar
{ {
config, config,
lib, lib,
self,
... ...
}: let }: let
unit = "gitea"; unit = "gitea";
@@ -22,20 +21,6 @@ in {
default = 5003; default = 5003;
description = "The port to host Gitea on."; description = "The port to host Gitea on.";
}; };
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;
default = "Gitea"; default = "Gitea";
@@ -54,109 +39,62 @@ in {
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
age.secrets = { services.${unit} = {
giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age"; enable = true;
}; appName = "cnix code forge";
server = { database = {
fail2ban = lib.mkIf config.server.fail2ban.enable { type = "postgres";
jails = { socket = "/run/postgresql";
gitea = { name = "gitea";
serviceName = "gitea"; user = "gitea";
failRegex = ''.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>''; createDatabase = false;
};
};
}; };
};
services = { lfs = {
cloudflared = {
enable = true; enable = true;
tunnels.${cfg.cloudflared.tunnelId} = {
credentialsFile = cfg.cloudflared.credentialsFile;
default = "http_status:404";
ingress."${cfg.url}".service = "http://localhost:${toString cfg.port}";
};
}; };
${unit} = { settings = {
enable = true; cors = {
appName = "cnix code forge"; ENABLED = true;
SCHEME = "https";
database = { ALLOW_DOMAIN = cfg.url;
type = "postgres";
socket = "/run/postgresql";
name = "gitea";
user = "gitea";
createDatabase = false;
}; };
log = {
lfs = { MODE = "console";
enable = true;
}; };
mailer = {
settings = { ENABLED = false;
cors = { MAILER_TYPE = "sendmail";
ENABLED = true; FROM = "noreply+adam@cnst.dev";
SCHEME = "https"; SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
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;
};
oauth2_client = {
ENABLE_AUTO_REGISTRATION = true;
ACCOUNT_LINKING = "auto";
};
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;
};
}; };
}; picture = {
}; DISABLE_GRAVATAR = true;
};
services.traefik = { repository = {
dynamicConfigOptions = { DEFAULT_BRANCH = "main";
http = { DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
services.gitea.loadBalancer.servers = [{url = "http://127.0.0.1:5003";}]; DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
routers = { };
gitea = { indexer = {
entryPoints = ["websecure"]; REPO_INDEXER_ENABLED = true;
rule = "Host(`${cfg.url}`)"; };
service = "gitea"; server = {
tls.certResolver = "letsencrypt"; DOMAIN = cfg.url;
# middlewares = ["authentik"]; 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;
}; };
}; };
}; };

View File

@@ -101,7 +101,7 @@ in {
label = "SYSTEM"; label = "SYSTEM";
memory = true; memory = true;
cpu = true; cpu = true;
uptime = false; uptime = true;
}; };
} }
]; ];
@@ -212,25 +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,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
self,
... ...
}: let }: let
unit = "jellyfin"; unit = "jellyfin";
@@ -18,7 +19,21 @@ in {
}; };
url = lib.mkOption { url = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "fin.${srv.tailscale.url}"; 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,24 +53,70 @@ in {
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.${unit} = { age.secrets = {
enable = true; jellyfinCloudflared = {
user = srv.user; file = "${self}/secrets/jellyfinCloudflared.age";
group = srv.group; 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;
user = srv.user;
group = srv.group;
};
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
jellyfin-ffmpeg jellyfin-ffmpeg
]; ];
services.traefik = { services.traefik = {
dynamicConfigOptions = { dynamicConfigOptions = {
http = { http = {
services.${unit}.loadBalancer.servers = [{url = "http://localhost:8096";}]; 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";}];
routers = { routers = {
jellyfinRouter = { jellyfin = {
entryPoints = ["websecure"]; entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)"; rule = "Host(`${cfg.url}`)";
service = "${unit}"; service = "jellyfin";
tls.certResolver = "letsencrypt"; tls.certResolver = "letsencrypt";
middlewares = ["authentik" "secureHeaders" "ratelimit"];
}; };
}; };
}; };

View File

@@ -3,18 +3,17 @@
lib, lib,
... ...
}: let }: let
unit = "jellyseerr"; service = "jellyseerr";
srv = config.server; srv = config.server;
cfg = config.server.${unit}; cfg = config.server.${service};
in { in {
options.server.${unit} = { options.server.${service} = {
enable = lib.mkEnableOption { enable = lib.mkEnableOption {
description = "Enable ${unit}"; description = "Enable ${service}";
}; };
url = lib.mkOption { url = lib.mkOption {
type = lib.types.str; type = lib.types.str;
# default = "seer.${srv.tailscale.url}"; default = "${service}.${srv.domain}";
default = "jellyseerr.${srv.domain}";
}; };
port = lib.mkOption { port = lib.mkOption {
type = lib.types.port; type = lib.types.port;
@@ -38,20 +37,21 @@ in {
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.${unit} = { services.${service} = {
enable = true; enable = true;
port = cfg.port; port = cfg.port;
}; };
services.traefik = { services.traefik = {
dynamicConfigOptions = { dynamicConfigOptions = {
http = { http = {
services.jellyseerr.loadBalancer.servers = [{url = "http://localhost:${toString cfg.port}";}]; services.jellyseerr.loadBalancer.servers = [{url = "http://127.0.0.1:${toString cfg.port}";}];
routers = { routers = {
jellyseerr = { jellyseerr = {
entryPoints = ["websecure"]; entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)"; rule = "Host(`${cfg.url}`)";
service = "${unit}"; service = "jellyseerr";
tls.certResolver = "letsencrypt"; tls.certResolver = "letsencrypt";
# middlewares = ["authentik"];
}; };
}; };
}; };

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

@@ -54,14 +54,8 @@ in {
server.fail2ban = lib.mkIf config.server.fail2ban.enable { server.fail2ban = lib.mkIf config.server.fail2ban.enable {
jails = { jails = {
nextcloud = { nextcloud = {
serviceName = "${unit}"; serviceName = "phpfpm-nextcloud";
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)''; failRegex = "^.*Login failed:.*(Remote IP: <HOST>).*$";
failRegex = ''
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Two-factor challenge failed:
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
'';
datePattern = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
}; };
}; };
}; };
@@ -69,7 +63,7 @@ in {
services = { services = {
${unit} = { ${unit} = {
enable = true; enable = true;
package = pkgs.nextcloud32; package = pkgs.nextcloud31;
hostName = "nextcloud"; hostName = "nextcloud";
configureRedis = true; configureRedis = true;
caching = { caching = {

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

@@ -34,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 {
@@ -143,64 +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 = {
@@ -208,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"
@@ -237,7 +179,7 @@ in {
autoStart = true; autoStart = true;
dependsOn = ["gluetun"]; dependsOn = ["gluetun"];
ports = [ ports = [
"8080:8080" "8387:8387"
"58846:58846" "58846:58846"
]; ];
extraOptions = [ extraOptions = [
@@ -295,7 +237,7 @@ in {
(lib.mkIf cfg.pihole.enable { (lib.mkIf cfg.pihole.enable {
pihole = { pihole = {
autoStart = true; autoStart = true;
image = "pihole/pihole:2025.08.0"; image = "pihole/pihole:latest";
volumes = [ volumes = [
"/var/lib/pihole:/etc/pihole/" "/var/lib/pihole:/etc/pihole/"
"/var/lib/dnsmasq.d:/etc/dnsmasq.d/" "/var/lib/dnsmasq.d:/etc/dnsmasq.d/"

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,31 +0,0 @@
{
config,
lib,
self,
...
}:
with lib; let
cfg = config.server.tailscale;
in {
options.server.tailscale = {
enable = mkEnableOption "Enable tailscale server configuration";
url = lib.mkOption {
type = lib.types.str;
default = "ts.cnst.dev";
};
};
config = mkIf cfg.enable {
age.secrets.sobotkaTsAuth.file = "${self}/secrets/sobotkaTsAuth.age";
services.tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
authKeyFile = config.age.secrets.sobotkaTsAuth.path;
extraSetFlags = [
"--advertise-exit-node"
];
};
};
}

View File

@@ -1,104 +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 = "traefik";
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 = {
vpn.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"];
}
{
main = "ts.cnst.dev";
sans = ["*ts.cnst.dev"];
}
];
};
};
};
};
};
};
};
}

View File

@@ -44,7 +44,7 @@ in {
jails = { jails = {
vaultwarden = { vaultwarden = {
serviceName = "vaultwarden"; serviceName = "vaultwarden";
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$''; failRegex = "^.*Username or password is incorrect. Try again. IP: <HOST>. Username: <F-USER>.*</F-USER>.$";
}; };
}; };
}; };
@@ -72,7 +72,7 @@ in {
logLevel = "warn"; logLevel = "warn";
extendedLogging = true; extendedLogging = true;
useSyslog = true; useSyslog = true;
invitationsAllowed = true; invitationsAllowed = false;
showPasswordHint = false; showPasswordHint = false;
}; };
}; };

View File

@@ -47,7 +47,7 @@ in {
nginx-404 = { nginx-404 = {
serviceName = "nginx"; serviceName = "nginx";
failRegex = ''^.*\[error\].*directory index of.* is forbidden.*client: <HOST>.*$''; failRegex = ''^.*\[error\].*directory index of.* is forbidden.*client: <HOST>.*$'';
ignoreRegex = ''''; ignoreRegex = "";
maxRetry = 5; maxRetry = 5;
}; };
}; };
@@ -114,18 +114,5 @@ in {
Disallow: / Disallow: /
''; '';
}; };
services.traefik.dynamicConfigOptions.http = {
routers.webfinger = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`) && Path(`/.well-known/webfinger`)";
service = "webfinger";
tls.certResolver = "letsencrypt";
};
services.webfinger.loadBalancer.servers = [
{url = "http://127.0.0.1:8283";}
];
};
}; };
} }

View File

@@ -1,12 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg RnlIwFO8LSwzj94G0Uru9qibXqOOpCU2kWWdNa2tRFU
lIC3K/jjBMKRfLfepoNYIkBe5rhHuR0l3Uf1Xuk8uZg
-> ssh-ed25519 KUYMFA k16GBRcaaSwJm/8+Vm2QBOu05u6eEro/7YYj7kbuNSU
VCpt918MBBFfFZKKypV9pSwz/Zhsxr+Ob6YjFuJ/oL0
-> ssh-ed25519 76RhUQ FIKn3nuOT1ywu6pmYBbpC54HhpJGeMFejp5c0XibfAY
WDsh/5G4wXYt21yIDxmI6u1l/xPOdZRxgTazf6QLXP8
-> ssh-ed25519 Jf8sqw 2EvD96Ec8h97ACoOBYzn1Ugx4ZyYSHIRnsmtB5lb/XQ
mFY8O8qwWWihsLe5ayB5iGm1JUY2B/9el/XSf5sPe7M
--- uuwibRk7LS4/lUx9gwL+x5NMrxLjGM1Yf55bzjxQTKM
<EFBFBD>H<>Ԅ6K<36>A<01>~<7E><>)!B<08><>^S!Wd<><64>$.:S'c<>d<EFBFBD><64><EFBFBD>_WW<57>Bj<42>,<2C><>l<EFBFBD><6C><EFBFBD><EFBFBD><EFBFBD>V<>S<EFBFBD><53>h<EFBFBD>
h<EFBFBD><EFBFBD><12><>k

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

@@ -48,7 +48,6 @@ in {
"homepageEnvironment.age".publicKeys = kima ++ sobotka; "homepageEnvironment.age".publicKeys = kima ++ sobotka;
"cloudflareFirewallApiKey.age".publicKeys = kima ++ sobotka; "cloudflareFirewallApiKey.age".publicKeys = kima ++ sobotka;
"vaultwardenCloudflared.age".publicKeys = kima ++ sobotka; "vaultwardenCloudflared.age".publicKeys = kima ++ sobotka;
"giteaCloudflared.age".publicKeys = kima ++ sobotka;
"nextcloudCloudflared.age".publicKeys = kima ++ sobotka; "nextcloudCloudflared.age".publicKeys = kima ++ sobotka;
"nextcloudAdminPass.age".publicKeys = kima ++ sobotka; "nextcloudAdminPass.age".publicKeys = kima ++ sobotka;
"cloudflareDnsApiToken.age".publicKeys = kima ++ sobotka; "cloudflareDnsApiToken.age".publicKeys = kima ++ sobotka;
@@ -59,10 +58,10 @@ in {
"sobotkaPihole.age".publicKeys = kima ++ sobotka; "sobotkaPihole.age".publicKeys = kima ++ sobotka;
"slskd.age".publicKeys = kima ++ sobotka; "slskd.age".publicKeys = kima ++ sobotka;
"authentikEnv.age".publicKeys = kima ++ sobotka; "authentikEnv.age".publicKeys = kima ++ sobotka;
"traefikEnv.age".publicKeys = kima ++ sobotka; "nginxEnv.age".publicKeys = kima ++ sobotka;
"wwwCloudflared.age".publicKeys = kima ++ sobotka; "wwwCloudflared.age".publicKeys = kima ++ sobotka;
"authentikCloudflared.age".publicKeys = kima ++ sobotka; "authentikCloudflared.age".publicKeys = kima ++ sobotka;
"sobotkaTsAuth.age".publicKeys = kima ++ sobotka; "jellyfinCloudflared.age".publicKeys = kima ++ sobotka;
# Ziggy-specific # Ziggy-specific
"cloudflareDnsCredentialsZiggy.age".publicKeys = kima ++ ziggy; "cloudflareDnsCredentialsZiggy.age".publicKeys = kima ++ ziggy;

View File

@@ -1,11 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg fftdt8orBZoM0sDRAXf0TScDLosNWWWIg7JmmuunuWM
2IfpTH6ptSyLnBtBStkk7SINct6LtBHrL6h22BVNb+k
-> ssh-ed25519 KUYMFA HI04mnVOGPRsRhnqCkbO4My/sBq5v/3UYxDVcfIe4RM
fcSApUYCnJlpzVW5e77CFoSHamEmP+6ztMmzp2WlJvY
-> ssh-ed25519 76RhUQ c2FbmTXGl/F+1acZFEJUoenkxiIGdoXkT67VgxvoFHg
eWExqblEp5VIeXuPEuvj4QAIWtFX5KLfMyh6/fZ9bnA
-> ssh-ed25519 Jf8sqw IAcUf70EufTyjsva8XIlXOfPxwXvtr9AFl0LwrdAMgc
bY098fejLaFbUMX0iF89gz8kiOGZHI8JIg4NzX4ItFw
--- WNqpLyRM2EqISbZky++NbKLw4GCEgwbz2O5+VO7aKzE
<EFBFBD><EFBFBD><1A><>(5<0F>q <09><>m<EFBFBD>C<EFBFBD><43>G<EFBFBD>r<><72><16><><EFBFBD><EFBFBD>ޒ3<DE92><33><17><1F>7<><37><EFBFBD>rG<72>i<EFBFBD>c7<63>i<EFBFBD>P<EFBFBD><50>l<EFBFBD><19>7<EFBFBD><<3C>r?cGo<47><>W<0E>V<EFBFBD><56>f,2<>Qg!<21>t_<74>

View File

@@ -1,11 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg 6LbgQLUp8wKmKVZZGAn5EvNxV2g4abypB3tEIxgUwhs
VFnsZlXZjmqj8rtIsOzEb7iIGL7+JrNZlnousl5ekR0
-> ssh-ed25519 KUYMFA oty0a3Sef9FuefKznWoDiw9zqXvEKOu2Bg/I+dWsICc
J81Edyq8eNrMZy8VHl1v1yeUBkyGSrwtuundzRjHD/Q
-> ssh-ed25519 76RhUQ jCHnm2LOCGN3BAbUrjsX9wFTDCecbcUTYRva7hPlPUs
q9BxGVVpUot7YFkg/+QKTuFtQwyR3Nk0QQuUgBbIR90
-> ssh-ed25519 Jf8sqw kX5+jV/HqPi5Hcv+iE0e1p/nAb8MmLmNY+Y3E6As3SA
C94zq34eFQABnxHoAjvXXf37rzmmEmzPUUrr9qD3Ir8
--- zTcJcdfAEEH6JZY1Fz2s4l3YuAl3B+2l4KkIZ7zqOd0
<EFBFBD><EFBFBD>֒<13> &<26> <0C><11><>W<EFBFBD><57>Ve<14><><EFBFBD>˲_M߾<4D>~<19><>y2<79>z<EFBFBD><7A>m<EFBFBD><6D>"椬<>VR,<2C>li<6C><69>/<2F><><EFBFBD><EFBFBD>YY