Compare commits
33 Commits
57cb48a11c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f9f3abee19 | |||
| 15bc0f211f | |||
| f0fb53b480 | |||
| 1ae85bd66e | |||
| 87b49d0f58 | |||
| c5a1c2861c | |||
| 8dc67e2b54 | |||
| 322136e4f3 | |||
| 300eb66afc | |||
| 545888878e | |||
| 5042675e0b | |||
| ece5e89a84 | |||
| 2933bcdf02 | |||
| 59e548f02e | |||
| 2ffc94161d | |||
| ff5490194b | |||
| 1dd06ef3f5 | |||
| ec9a3bd845 | |||
| 2c08f78586 | |||
| d22801168f | |||
| 0c86dc56bd | |||
| 3d8deae6f3 | |||
| cd978f5eb6 | |||
| 64df7abad5 | |||
| 8efa649d47 | |||
| 2dc09e23a0 | |||
| 8fd2a7d9ad | |||
| 113892b75d | |||
| 001dfbf27f | |||
| 3deca06206 | |||
| 07333b4544 | |||
| 63f495fa0d | |||
| d2bd385367 |
342
flake.lock
generated
342
flake.lock
generated
@@ -8,11 +8,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1754433428,
|
||||
"narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=",
|
||||
"lastModified": 1761656077,
|
||||
"narHash": "sha256-lsNWuj4Z+pE7s0bd2OKicOFq9bK86JE0ZGeKJbNqb94=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d",
|
||||
"rev": "9ba0d85de3eaa7afeab493fed622008b6e4924f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -29,11 +29,11 @@
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760083914,
|
||||
"narHash": "sha256-I9IMO9d+z71oeqOz6gOre07tK2Du3vp2FcOW3x4FDXw=",
|
||||
"lastModified": 1761806975,
|
||||
"narHash": "sha256-GLGdVJSPH0LnsO64Biw0WFJaj1PlltYxgH13f+FGWgQ=",
|
||||
"owner": "anyrun-org",
|
||||
"repo": "anyrun",
|
||||
"rev": "3050aa30e25957bbb9e1ac91a44d3979eccadf59",
|
||||
"rev": "329d31af9ba038ef65db9914eb94de695c738377",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -83,11 +83,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759499898,
|
||||
"narHash": "sha256-UNzYHLWfkSzLHDep5Ckb5tXc0fdxwPIrT+MY4kpQttM=",
|
||||
"lastModified": 1760101617,
|
||||
"narHash": "sha256-8jf/3ZCi+B7zYpIyV04+3wm72BD7Z801IlOzsOACR7I=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "655e067f96fd44b3f5685e17f566b0e4d535d798",
|
||||
"rev": "1826a9923881320306231b1c2090379ebf9fa4f8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -100,14 +100,10 @@
|
||||
"inputs": {
|
||||
"authentik-src": "authentik-src",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-parts": [
|
||||
"flake-parts"
|
||||
],
|
||||
"flake-parts": "flake-parts_2",
|
||||
"flake-utils": "flake-utils",
|
||||
"napalm": "napalm",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"pyproject-build-systems": "pyproject-build-systems",
|
||||
"pyproject-nix": "pyproject-nix",
|
||||
"systems": "systems_3",
|
||||
@@ -123,6 +119,7 @@
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "version/2025.8.4",
|
||||
"repo": "authentik-nix",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -149,15 +146,15 @@
|
||||
"flake-schemas": "flake-schemas",
|
||||
"home-manager": "home-manager_2",
|
||||
"jovian": "jovian",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760148209,
|
||||
"narHash": "sha256-ssMUeLk1cmLqzNMW6l9dgGoLtOY9F9dEGplJlWJmNis=",
|
||||
"lastModified": 1762036128,
|
||||
"narHash": "sha256-0VgVPYq5upSXc+LSn3ubxJhH+DLdakYW4QXeabo0Ivg=",
|
||||
"owner": "chaotic-cx",
|
||||
"repo": "nyx",
|
||||
"rev": "b51bb724939dbfa264f08522efffce2bb47b6135",
|
||||
"rev": "499783c86e6e9436534d1a23b35da98c7f6af3f4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -212,11 +209,11 @@
|
||||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760164678,
|
||||
"narHash": "sha256-yxcfwZCysR6zPaFv7is3/FWd1h0h6kXME0vueSwTBhU=",
|
||||
"lastModified": 1762065744,
|
||||
"narHash": "sha256-c04mxJoCb8f6BBrdaREWmdQq+pfp395olXhC+B0G7DI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "2579f163559b902959cc420a6d3bfbd98c46a323",
|
||||
"rev": "e0f24085a4a0da1c32adc308ec4c518ae886ff35",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -243,11 +240,11 @@
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"locked": {
|
||||
"lastModified": 1747046372,
|
||||
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||
"lastModified": 1761588595,
|
||||
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -327,16 +324,14 @@
|
||||
},
|
||||
"flake-parts_2": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nixpkgs"
|
||||
]
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759362264,
|
||||
"narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=",
|
||||
"lastModified": 1756770412,
|
||||
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "758cf7296bee11f1706a574c77d072b8a7baa881",
|
||||
"rev": "4524271976b625a4a605beefd893f270620fd751",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -347,7 +342,27 @@
|
||||
},
|
||||
"flake-parts_3": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
"nixpkgs-lib": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1762040540,
|
||||
"narHash": "sha256-z5PlZ47j50VNF3R+IMS9LmzI5fYRGY/Z5O5tol1c9I4=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "0010412d62a25d959151790968765a70c436598b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_4": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1753121425,
|
||||
@@ -363,7 +378,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_4": {
|
||||
"flake-parts_5": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"lanzaboote",
|
||||
@@ -384,7 +399,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_5": {
|
||||
"flake-parts_6": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nvf",
|
||||
@@ -392,11 +407,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759362264,
|
||||
"narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=",
|
||||
"lastModified": 1760948891,
|
||||
"narHash": "sha256-TmWcdiUUaWk8J4lpjzu4gCGxWY6/Ok7mOK4fIFfBuU4=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "758cf7296bee11f1706a574c77d072b8a7baa881",
|
||||
"rev": "864599284fc7c0ba6357ed89ed5e2cd5040f0c04",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -405,7 +420,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_6": {
|
||||
"flake-parts_7": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"tuirun",
|
||||
@@ -463,8 +478,8 @@
|
||||
},
|
||||
"fonts": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts_3",
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
"flake-parts": "flake-parts_4",
|
||||
"nixpkgs": "nixpkgs_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1753431871,
|
||||
@@ -491,11 +506,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759523803,
|
||||
"narHash": "sha256-PTod9NG+i3XbbnBKMl/e5uHDBYpwIWivQ3gOWSEuIEM=",
|
||||
"lastModified": 1760663237,
|
||||
"narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "cfc9f7bb163ad8542029d303e599c0f7eee09835",
|
||||
"rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -571,11 +586,11 @@
|
||||
},
|
||||
"hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1760106635,
|
||||
"narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=",
|
||||
"lastModified": 1761933221,
|
||||
"narHash": "sha256-rNHeoG3ZrA94jczyLSjxCtu67YYPYIlXXr0uhG3wNxM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903",
|
||||
"rev": "7467f155fcba189eb088a7601f44fbef7688669b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -586,15 +601,15 @@
|
||||
},
|
||||
"helix-flake": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_5",
|
||||
"nixpkgs": "nixpkgs_6",
|
||||
"rust-overlay": "rust-overlay_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759850138,
|
||||
"narHash": "sha256-fYHIxjTvVIAEDWzenUROuzDPxy1rBCXZNPgh4b1dfgo=",
|
||||
"lastModified": 1762054696,
|
||||
"narHash": "sha256-4wyNPyycaPDS13OC+YPkQOrrf3ZCS/ipAh9lfo121Nw=",
|
||||
"owner": "helix-editor",
|
||||
"repo": "helix",
|
||||
"rev": "5b0563419eeeaf0595c848865c46be4abad246a7",
|
||||
"rev": "0b61e721aaae794c950c72f765388dcc5f9f32fa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -610,11 +625,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760130406,
|
||||
"narHash": "sha256-GKMwBaFRw/C1p1VtjDz4DyhyzjKUWyi1K50bh8lgA2E=",
|
||||
"lastModified": 1762087455,
|
||||
"narHash": "sha256-hpbPma1eUKwLAmiVRoMgIHbHiIKFkcACobJLbDt6ABw=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "d305eece827a3fe317a2d70138f53feccaf890a1",
|
||||
"rev": "43e205606aeb253bfcee15fd8a4a01d8ce8384ca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -652,11 +667,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760061988,
|
||||
"narHash": "sha256-CeuMo7fjWm3XaoK+b1PGyaVIlE1GHudoxk9jrJFvfbY=",
|
||||
"lastModified": 1761878381,
|
||||
"narHash": "sha256-lCRaipHgszaFZ1Cs8fdGJguVycCisBAf2HEFgip5+xU=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "c7f4214faca2f196c551b767c12a70bfa0614510",
|
||||
"rev": "4ac96eb21c101a3e5b77ba105febc5641a8959aa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -710,11 +725,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759490292,
|
||||
"narHash": "sha256-T6iWzDOXp8Wv0KQOCTHpBcmAOdHJ6zc/l9xaztW6Ivc=",
|
||||
"lastModified": 1760445448,
|
||||
"narHash": "sha256-fXGjL6dw31FPFRrmIemzGiNSlfvEJTJNsmadZi+qNhI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "9431db625cd9bb66ac55525479dce694101d6d7a",
|
||||
"rev": "50fb9f069219f338a11cf0bcccb9e58357d67757",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -774,11 +789,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1757420192,
|
||||
"narHash": "sha256-jVkY2ax7e+V+M4RwLZTJnOVTdjR5Bj10VstJuK60tl4=",
|
||||
"lastModified": 1762027241,
|
||||
"narHash": "sha256-w0NhWx95Xao6Dh3G1p7G1cHwGBknwPVPG5VRghk3LSg=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hypridle",
|
||||
"rev": "f158b2fe9293f9b25f681b8e46d84674e7bc7f01",
|
||||
"rev": "f3d1f3b232a5e3267008568196397b03fab244d2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -797,17 +812,17 @@
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner_2",
|
||||
"nixpkgs": "nixpkgs_6",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
"systems": "systems_4",
|
||||
"xdph": "xdph"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760143218,
|
||||
"narHash": "sha256-OhJPROcRcwBkjOKkXr/f3/7wuSjhAIqr8WfmEUF9Uuo=",
|
||||
"lastModified": 1761869718,
|
||||
"narHash": "sha256-jLfwwlPGpnGRAtVDyoGj9FgH2D9hWwyEu0yHkflG2EI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland",
|
||||
"rev": "d599513d4a72d66ac62ffdedc41d6653fa81b39e",
|
||||
"rev": "8e9add2afda58d233a75e4c5ce8503b24fa59ceb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -874,11 +889,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749046714,
|
||||
"narHash": "sha256-kymV5FMnddYGI+UjwIw8ceDjdeg7ToDVjbHCvUlhn14=",
|
||||
"lastModified": 1759610243,
|
||||
"narHash": "sha256-+KEVnKBe8wz+a6dTLq8YDcF3UrhQElwsYJaVaHXJtoI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "613878cb6f459c5e323aaafe1e6f388ac8a36330",
|
||||
"rev": "bd153e76f751f150a09328dbdeb5e4fab9d23622",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1006,11 +1021,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760023949,
|
||||
"narHash": "sha256-fu0B4duamVdbkPio/czu1XhsPLRXUJpZLDrSk3nih4U=",
|
||||
"lastModified": 1761675634,
|
||||
"narHash": "sha256-Et1jNDB2d3e0b4okIKuyAMktECS+5hk+vMAA7X598ao=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlock",
|
||||
"rev": "36ec73f166d9434a3f27c96c575198906f77644a",
|
||||
"rev": "98b86752fe4867bd14ef96a92ea788229af93130",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1191,11 +1206,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759815224,
|
||||
"narHash": "sha256-HbdOyjqHm38j6o5mV24i0bn+r5ykS+VJBnWJuZ0fE+A=",
|
||||
"lastModified": 1761748321,
|
||||
"narHash": "sha256-hD5mVzmUeyVppjArdy2uVdQe/CQUR9i3WgZB05onE7A=",
|
||||
"owner": "Jovian-Experiments",
|
||||
"repo": "Jovian-NixOS",
|
||||
"rev": "ee974f496a080c61b3164992c850f43741edcc52",
|
||||
"rev": "533db5857c9e00ca352558a928417116ee08a824",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1208,8 +1223,8 @@
|
||||
"inputs": {
|
||||
"crane": "crane",
|
||||
"flake-compat": "flake-compat_4",
|
||||
"flake-parts": "flake-parts_4",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"flake-parts": "flake-parts_5",
|
||||
"nixpkgs": "nixpkgs_8",
|
||||
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
|
||||
"rust-overlay": "rust-overlay_3"
|
||||
},
|
||||
@@ -1278,11 +1293,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760146997,
|
||||
"narHash": "sha256-x2sF8Q4tWz3DI166s+KFDXySrK+cN+/YEd3DfhnhBLQ=",
|
||||
"lastModified": 1762088055,
|
||||
"narHash": "sha256-zh7fDPmhmoXVTtODiDhOLlutwNLJmwOlLphVKuCCiZA=",
|
||||
"owner": "fufexan",
|
||||
"repo": "nix-gaming",
|
||||
"rev": "ad505387568d024654da88fef03d9c5319cba92f",
|
||||
"rev": "d74c3702fdc737276baccab80c2053e8cde5dba5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1331,6 +1346,21 @@
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1754788789,
|
||||
"narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "a73b9c743612e4244d865a2fdee11865283c04e6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib_2": {
|
||||
"locked": {
|
||||
"lastModified": 1751159883,
|
||||
"narHash": "sha256-urW/Ylk9FIfvXfliA1ywh75yszAbiTEVgpPeinFyVZo=",
|
||||
@@ -1345,6 +1375,22 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_10": {
|
||||
"locked": {
|
||||
"lastModified": 1761880412,
|
||||
"narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a7fc11be66bdfb5cdde611ee5ce381c183da8386",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1758690382,
|
||||
@@ -1363,11 +1409,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1760038930,
|
||||
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=",
|
||||
"lastModified": 1757745802,
|
||||
"narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3",
|
||||
"rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1378,6 +1424,22 @@
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1761907660,
|
||||
"narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1753250450,
|
||||
"narHash": "sha256-i+CQV2rPmP8wHxj0aq4siYyohHwVlsh40kV89f3nw1s=",
|
||||
@@ -1393,39 +1455,39 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1759381078,
|
||||
"narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1759381078,
|
||||
"narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
|
||||
"owner": "NixOS",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_7": {
|
||||
"locked": {
|
||||
"lastModified": 1761114652,
|
||||
"narHash": "sha256-f/QCJM/YhrV/lavyCVz8iU3rlZun6d+dAiC3H+CDle4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "01f116e4df6a15f4ccdffb1bcd41096869fb385c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_8": {
|
||||
"locked": {
|
||||
"lastModified": 1754243818,
|
||||
"narHash": "sha256-sEPw2W01UPf0xNGnMGNZIaE1XHkk7O+lLLetYEXVZHk=",
|
||||
@@ -1441,13 +1503,13 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_8": {
|
||||
"nixpkgs_9": {
|
||||
"locked": {
|
||||
"lastModified": 1760038930,
|
||||
"narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=",
|
||||
"lastModified": 1761907660,
|
||||
"narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3",
|
||||
"rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1457,36 +1519,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_9": {
|
||||
"locked": {
|
||||
"lastModified": 1759386674,
|
||||
"narHash": "sha256-wg1Lz/1FC5Q13R+mM5a2oTV9TA9L/CHHTm3/PiLayfA=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "625ad6366178f03acd79f9e3822606dd7985b657",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nvf": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_5",
|
||||
"flake-parts": "flake-parts_5",
|
||||
"flake-parts": "flake-parts_6",
|
||||
"mnw": "mnw",
|
||||
"nixpkgs": "nixpkgs_9",
|
||||
"nixpkgs": "nixpkgs_10",
|
||||
"systems": "systems_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760153667,
|
||||
"narHash": "sha256-F7KmXT/Izse6Q6CkD5GCImoGPaDJxl03Kd7eD+eY/bU=",
|
||||
"lastModified": 1762093557,
|
||||
"narHash": "sha256-esmyNNa8TvduITLfqYPSMroyZ9vxJr2nsvjYmHmO+Ag=",
|
||||
"owner": "notashelf",
|
||||
"repo": "nvf",
|
||||
"rev": "9df9d51fd9fc8f9a8fc377f984ea3b7ae796172d",
|
||||
"rev": "20d8fca94dceaf943686598da7fba31b37100e50",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1505,11 +1551,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1758108966,
|
||||
"narHash": "sha256-ytw7ROXaWZ7OfwHrQ9xvjpUWeGVm86pwnEd1QhzawIo=",
|
||||
"lastModified": 1760663237,
|
||||
"narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "54df955a695a84cd47d4a43e08e1feaf90b1fd9b",
|
||||
"rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1602,7 +1648,7 @@
|
||||
"chaotic": "chaotic",
|
||||
"fenix": "fenix",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"flake-parts": "flake-parts_3",
|
||||
"fonts": "fonts",
|
||||
"git-hooks": "git-hooks",
|
||||
"hardware": "hardware",
|
||||
@@ -1615,7 +1661,7 @@
|
||||
"hyprpaper": "hyprpaper",
|
||||
"lanzaboote": "lanzaboote",
|
||||
"nix-gaming": "nix-gaming",
|
||||
"nixpkgs": "nixpkgs_8",
|
||||
"nixpkgs": "nixpkgs_9",
|
||||
"nvf": "nvf",
|
||||
"systems": "systems_6",
|
||||
"treefmt-nix": "treefmt-nix",
|
||||
@@ -1626,11 +1672,11 @@
|
||||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1760090851,
|
||||
"narHash": "sha256-XGkBjf4Dzg6tXd0KGgKzeW4oVX/iLzLhD3rQ1cATpqM=",
|
||||
"lastModified": 1762016333,
|
||||
"narHash": "sha256-PT8hXDYyeRjh9BGyLF/nZWm9TqRwP2EzeKuqUFH0M3w=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "b93180b4f2cb3c81ac7f17f46e3dfcb30ecc7843",
|
||||
"rev": "fca718c0f2074bdccf9a996bb37b0fcaff80dc97",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1648,11 +1694,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760063676,
|
||||
"narHash": "sha256-s5Fjh43skH2L+avOGioLmEHoYZffDbg3abV5h0gjeew=",
|
||||
"lastModified": 1761964689,
|
||||
"narHash": "sha256-Zo3LQQDz+64EQ9zor/WmeNTFLoZkjmhp0UY3G0D3seE=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "897deed0923cc5a1d560c5176abe0d172ec9716d",
|
||||
"rev": "63d22578600f70d293aede6bc737efef60ebd97f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1815,11 +1861,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1760120816,
|
||||
"narHash": "sha256-gq9rdocpmRZCwLS5vsHozwB6b5nrOBDNc2kkEaTXHfg=",
|
||||
"lastModified": 1761311587,
|
||||
"narHash": "sha256-Msq86cR5SjozQGCnC6H8C+0cD4rnx91BPltZ9KK613Y=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "761ae7aff00907b607125b2f57338b74177697ed",
|
||||
"rev": "2eddae033e4e74bf581c2d1dfa101f9033dbd2dc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1830,7 +1876,7 @@
|
||||
},
|
||||
"tuirun": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts_6",
|
||||
"flake-parts": "flake-parts_7",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -1903,11 +1949,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755354946,
|
||||
"narHash": "sha256-zdov5f/GcoLQc9qYIS1dUTqtJMeDqmBmo59PAxze6e4=",
|
||||
"lastModified": 1760713634,
|
||||
"narHash": "sha256-5HXelmz2x/uO26lvW7MudnadbAfoBnve4tRBiDVLtOM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "a10726d6a8d0ef1a0c645378f983b6278c42eaa0",
|
||||
"rev": "753bbbdf6a052994da94062e5b753288cef28dfb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1923,11 +1969,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1759969704,
|
||||
"narHash": "sha256-T7f/invcFIKHrBqD+FLf/C/HOGmpYfbZUzTDxFscpOA=",
|
||||
"lastModified": 1762074512,
|
||||
"narHash": "sha256-m8ZY0rmq9QXnIR08/vOyK9MnEbiziZG8mPGAVwoYEPQ=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "1173c777dc8daddcc4959260a7b00fd8abc884c5",
|
||||
"revCount": 137,
|
||||
"rev": "eb05f21bcf0f380e45537db6c5df13b50acaa4a6",
|
||||
"revCount": 143,
|
||||
"type": "git",
|
||||
"url": "https://git.sr.ht/~canasta/zen-browser-flake"
|
||||
},
|
||||
|
||||
15
flake.nix
15
flake.nix
@@ -1,8 +1,7 @@
|
||||
{
|
||||
description = "cnix nix";
|
||||
|
||||
outputs =
|
||||
inputs:
|
||||
outputs = inputs:
|
||||
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
@@ -17,13 +16,11 @@
|
||||
./fmt-hooks.nix
|
||||
];
|
||||
|
||||
perSystem =
|
||||
{
|
||||
perSystem = {
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
}: {
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = [
|
||||
pkgs.git
|
||||
@@ -56,11 +53,7 @@
|
||||
};
|
||||
|
||||
authentik = {
|
||||
url = "github:nix-community/authentik-nix";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-parts.follows = "flake-parts";
|
||||
};
|
||||
url = "github:nix-community/authentik-nix/version/2025.8.4";
|
||||
};
|
||||
|
||||
flake-compat.url = "github:edolstra/flake-compat";
|
||||
|
||||
@@ -38,17 +38,11 @@ in
|
||||
./settings.nix
|
||||
];
|
||||
|
||||
boot.initrd.luks.devices."luks-0ad53967-bb38-4485-be75-ca55ae4c3b68".device = "/dev/disk/by-uuid/0ad53967-bb38-4485-be75-ca55ae4c3b68";
|
||||
networking.hostName = "bunk";
|
||||
|
||||
swapDevices = [
|
||||
{
|
||||
device = "/var/lib/swapfile";
|
||||
size = 32 * 1024;
|
||||
}
|
||||
];
|
||||
|
||||
environment.variables.NH_FLAKE = "/home/cnst/.nix-config";
|
||||
|
||||
# https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
|
||||
system.stateVersion = lib.mkDefault "23.11";
|
||||
system.stateVersion = lib.mkDefault "25.05";
|
||||
}
|
||||
|
||||
@@ -1,48 +1,36 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
||||
boot = {
|
||||
initrd = {
|
||||
availableKernelModules = [
|
||||
"nvme"
|
||||
"xhci_pci"
|
||||
"ahci"
|
||||
"usbhid"
|
||||
"usb_storage"
|
||||
"sd_mod"
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
kernelModules = [ "amdgpu" ];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "usb_storage" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/d15672b5-dc97-4f99-9ad2-70f9ddf20447";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@" ];
|
||||
};
|
||||
|
||||
kernelModules = [ "kvm-amd" ];
|
||||
extraModulePackages = [ ];
|
||||
};
|
||||
boot.initrd.luks.devices."luks-2f0dfe96-bc63-4f38-b190-3d9fa45dc560".device = "/dev/disk/by-uuid/2f0dfe96-bc63-4f38-b190-3d9fa45dc560";
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/da41c89a-7ab8-4697-9a14-0d115b97cc2e";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
boot.initrd.luks.devices."luks-e75ac560-748f-4071-bbe7-479678400be3".device =
|
||||
"/dev/disk/by-uuid/e75ac560-748f-4071-bbe7-479678400be3";
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/7E84-D168";
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/F3FC-3CDF";
|
||||
fsType = "vfat";
|
||||
options = [
|
||||
"fmask=0022"
|
||||
"dmask=0022"
|
||||
];
|
||||
options = [ "fmask=0077" "dmask=0077" ];
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/e6464248-0d1e-4950-bf48-4cebeabaf871"; }
|
||||
];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
# still possible to use this option, but it's recommended to use it in conjunction
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
};
|
||||
network = {
|
||||
enable = true;
|
||||
nameservers = [
|
||||
"192.168.88.1"
|
||||
"192.168.88.69"
|
||||
];
|
||||
search = [
|
||||
"taila7448a.ts.net"
|
||||
];
|
||||
interfaces = {
|
||||
"wlp6s0" = {
|
||||
allowedTCPPorts = [
|
||||
@@ -73,8 +80,8 @@
|
||||
enable = false;
|
||||
};
|
||||
hyprland = {
|
||||
enable = false;
|
||||
withUWSM = false;
|
||||
enable = true;
|
||||
withUWSM = true;
|
||||
};
|
||||
inkscape = {
|
||||
enable = false;
|
||||
@@ -86,7 +93,7 @@
|
||||
enable = true;
|
||||
};
|
||||
niri = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
};
|
||||
pkgs = {
|
||||
enable = true;
|
||||
@@ -123,10 +130,10 @@
|
||||
enable = false;
|
||||
};
|
||||
thunar = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
};
|
||||
yubikey = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
};
|
||||
zsh = {
|
||||
enable = false;
|
||||
@@ -168,7 +175,7 @@
|
||||
enable = true;
|
||||
};
|
||||
mullvad = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
};
|
||||
nix-ld = {
|
||||
enable = false;
|
||||
@@ -191,11 +198,14 @@
|
||||
samba = {
|
||||
enable = false;
|
||||
};
|
||||
tailscale = {
|
||||
enable = true;
|
||||
};
|
||||
udisks = {
|
||||
enable = true;
|
||||
};
|
||||
zram = {
|
||||
enable = false;
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
system = {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
name = "DP-3";
|
||||
width = 2560;
|
||||
height = 1440;
|
||||
refreshRate = 240;
|
||||
refreshRate = "143.99";
|
||||
position = "0x0";
|
||||
transform = 0;
|
||||
bitDepth = 10;
|
||||
@@ -20,7 +20,7 @@
|
||||
name = "HDMI-A-1";
|
||||
width = 1920;
|
||||
height = 1080;
|
||||
refreshRate = 60;
|
||||
refreshRate = "60";
|
||||
position = "2560x0";
|
||||
# transform = 3;
|
||||
workspace = "5";
|
||||
@@ -29,7 +29,7 @@
|
||||
name = "eDP-1";
|
||||
width = 1920;
|
||||
height = 1200;
|
||||
refreshRate = 60;
|
||||
refreshRate = "60";
|
||||
workspace = "1";
|
||||
}
|
||||
];
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{
|
||||
flake.nixosConfigurations =
|
||||
let
|
||||
cLib = import ../lib inputs.nixpkgs.lib;
|
||||
clib = import ../lib inputs.nixpkgs.lib;
|
||||
userConfig = "${self}/home";
|
||||
systemConfig = "${self}/system";
|
||||
hostConfig = "${self}/hosts";
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
specialArgs = {
|
||||
inherit
|
||||
cLib
|
||||
inputs
|
||||
outputs
|
||||
self
|
||||
@@ -37,17 +36,20 @@
|
||||
smodPath
|
||||
;
|
||||
};
|
||||
specialArgsWithClib = specialArgs // {
|
||||
inherit clib;
|
||||
};
|
||||
in
|
||||
{
|
||||
kima = nixosSystem {
|
||||
inherit specialArgs;
|
||||
specialArgs = specialArgsWithClib;
|
||||
modules = [
|
||||
./kima
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.cnst.imports = homeImports."cnst@kima";
|
||||
extraSpecialArgs = specialArgs;
|
||||
extraSpecialArgs = specialArgsWithClib;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
@@ -57,14 +59,14 @@
|
||||
];
|
||||
};
|
||||
bunk = nixosSystem {
|
||||
inherit specialArgs;
|
||||
specialArgs = specialArgsWithClib;
|
||||
modules = [
|
||||
./bunk
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.cnst.imports = homeImports."cnst@bunk";
|
||||
extraSpecialArgs = specialArgs;
|
||||
extraSpecialArgs = specialArgsWithClib;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
@@ -97,14 +99,14 @@
|
||||
];
|
||||
};
|
||||
toothpc = nixosSystem {
|
||||
inherit specialArgs;
|
||||
specialArgs = specialArgsWithClib;
|
||||
modules = [
|
||||
./toothpc
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.toothpick.imports = homeImports."toothpick@toothpc";
|
||||
extraSpecialArgs = specialArgs;
|
||||
extraSpecialArgs = specialArgsWithClib;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
enable = false;
|
||||
};
|
||||
hyprland = {
|
||||
enable = false;
|
||||
withUWSM = false;
|
||||
enable = true;
|
||||
withUWSM = true;
|
||||
};
|
||||
inkscape = {
|
||||
enable = false;
|
||||
@@ -98,7 +98,7 @@
|
||||
enable = true;
|
||||
};
|
||||
niri = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
};
|
||||
pkgs = {
|
||||
enable = true;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
name = "DP-3";
|
||||
width = 2560;
|
||||
height = 1440;
|
||||
refreshRate = 240;
|
||||
refreshRate = "143.99";
|
||||
position = "0x0";
|
||||
transform = 0;
|
||||
bitDepth = 10;
|
||||
@@ -20,7 +20,7 @@
|
||||
name = "HDMI-A-1";
|
||||
width = 1920;
|
||||
height = 1080;
|
||||
refreshRate = 60;
|
||||
refreshRate = "60";
|
||||
position = "2560x0";
|
||||
transform = 3;
|
||||
workspace = "5";
|
||||
@@ -29,7 +29,7 @@
|
||||
name = "eDP-1";
|
||||
width = 1920;
|
||||
height = 1200;
|
||||
refreshRate = 60;
|
||||
refreshRate = "60";
|
||||
workspace = "1";
|
||||
}
|
||||
];
|
||||
|
||||
@@ -3,11 +3,22 @@
|
||||
enable = true;
|
||||
email = "adam@cnst.dev";
|
||||
domain = "cnix.dev";
|
||||
ip = "192.168.88.14";
|
||||
user = "share";
|
||||
group = "share";
|
||||
uid = 994;
|
||||
gid = 993;
|
||||
|
||||
infra = {
|
||||
authentik = {
|
||||
enable = true;
|
||||
url = "auth.cnst.dev";
|
||||
port = 9000;
|
||||
cloudflared = {
|
||||
tunnelId = "b66f9368-db9e-4302-8b48-527cda34a635";
|
||||
credentialsFile = config.age.secrets.authentikCloudflared.path;
|
||||
};
|
||||
};
|
||||
traefik = {
|
||||
enable = true;
|
||||
};
|
||||
@@ -17,72 +28,6 @@
|
||||
unbound = {
|
||||
enable = true;
|
||||
};
|
||||
homepage-dashboard = {
|
||||
enable = true;
|
||||
};
|
||||
n8n = {
|
||||
enable = true;
|
||||
};
|
||||
bazarr = {
|
||||
enable = true;
|
||||
};
|
||||
prowlarr = {
|
||||
enable = true;
|
||||
};
|
||||
lidarr = {
|
||||
enable = true;
|
||||
};
|
||||
sonarr = {
|
||||
enable = true;
|
||||
};
|
||||
radarr = {
|
||||
enable = true;
|
||||
};
|
||||
jellyseerr = {
|
||||
enable = true;
|
||||
};
|
||||
jellyfin = {
|
||||
enable = true;
|
||||
};
|
||||
uptime-kuma = {
|
||||
enable = true;
|
||||
};
|
||||
gitea = {
|
||||
enable = true;
|
||||
url = "git.cnst.dev";
|
||||
cloudflared = {
|
||||
tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
|
||||
credentialsFile = config.age.secrets.giteaCloudflared.path;
|
||||
};
|
||||
};
|
||||
vaultwarden = {
|
||||
enable = true;
|
||||
url = "vault.cnst.dev";
|
||||
cloudflared = {
|
||||
tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
||||
credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
||||
};
|
||||
};
|
||||
www = {
|
||||
enable = true;
|
||||
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 = {
|
||||
enable = true;
|
||||
adminpassFile = config.age.secrets.nextcloudAdminPass.path;
|
||||
};
|
||||
fail2ban = {
|
||||
enable = true;
|
||||
apiKeyFile = config.age.secrets.cloudflareFirewallApiKey.path;
|
||||
@@ -92,19 +37,242 @@
|
||||
enable = true;
|
||||
interface = "enp6s0";
|
||||
};
|
||||
gluetun = {
|
||||
enable = true;
|
||||
};
|
||||
podman = {
|
||||
enable = true;
|
||||
gluetun.enable = true;
|
||||
};
|
||||
www = {
|
||||
enable = true;
|
||||
url = "cnst.dev";
|
||||
port = 8283;
|
||||
cloudflared = {
|
||||
tunnelId = "e5076186-efb7-405a-998c-6155af7fb221";
|
||||
credentialsFile = config.age.secrets.wwwCloudflared.path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
homepage-dashboard = {
|
||||
enable = true;
|
||||
subdomain = "dash";
|
||||
exposure = "local";
|
||||
port = 8082;
|
||||
};
|
||||
n8n = {
|
||||
enable = true;
|
||||
subdomain = "n8n";
|
||||
exposure = "local";
|
||||
port = 5678;
|
||||
homepage = {
|
||||
name = "n8n";
|
||||
description = "A workflow automation platform";
|
||||
icon = "n8n.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
ollama = {
|
||||
enable = true;
|
||||
subdomain = "ai";
|
||||
exposure = "local";
|
||||
port = 8001;
|
||||
homepage = {
|
||||
name = "ollama";
|
||||
description = "AI platform";
|
||||
icon = "ollama.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
bazarr = {
|
||||
enable = true;
|
||||
subdomain = "bazarr";
|
||||
exposure = "local";
|
||||
port = 6767;
|
||||
homepage = {
|
||||
name = "Bazarr";
|
||||
description = "Subtitle manager";
|
||||
icon = "bazarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
prowlarr = {
|
||||
enable = true;
|
||||
subdomain = "prowlarr";
|
||||
exposure = "local";
|
||||
port = 9696;
|
||||
homepage = {
|
||||
name = "Prowlarr";
|
||||
description = "PVR indexer";
|
||||
icon = "prowlarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
flaresolverr = {
|
||||
enable = true;
|
||||
subdomain = "flaresolverr";
|
||||
exposure = "local";
|
||||
port = 8191;
|
||||
homepage = {
|
||||
name = "FlareSolverr";
|
||||
description = "Proxy to bypass Cloudflare/DDoS-GUARD protection";
|
||||
icon = "flaresolverr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
lidarr = {
|
||||
enable = true;
|
||||
subdomain = "lidarr";
|
||||
exposure = "local";
|
||||
port = 8686;
|
||||
homepage = {
|
||||
name = "Lidarr";
|
||||
description = "Music collection manager";
|
||||
icon = "lidarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
sonarr = {
|
||||
enable = true;
|
||||
subdomain = "sonarr";
|
||||
exposure = "local";
|
||||
port = 8989;
|
||||
homepage = {
|
||||
name = "Sonarr";
|
||||
description = "Internet PVR for Usenet and Torrents";
|
||||
icon = "sonarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
radarr = {
|
||||
enable = true;
|
||||
subdomain = "radarr";
|
||||
exposure = "local";
|
||||
port = 7878;
|
||||
homepage = {
|
||||
name = "Radarr";
|
||||
description = "Movie collection manager";
|
||||
icon = "radarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
jellyseerr = {
|
||||
enable = true;
|
||||
subdomain = "jellyseerr";
|
||||
exposure = "local";
|
||||
port = 5055;
|
||||
homepage = {
|
||||
name = "Jellyseerr";
|
||||
description = "Media request and discovery manager";
|
||||
icon = "jellyseerr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
jellyfin = {
|
||||
enable = true;
|
||||
subdomain = "fin";
|
||||
exposure = "tailscale";
|
||||
port = 8096;
|
||||
homepage = {
|
||||
name = "Jellyfin";
|
||||
description = "The Free Software Media System";
|
||||
icon = "jellyfin.svg";
|
||||
category = "Media";
|
||||
};
|
||||
};
|
||||
uptime-kuma = {
|
||||
enable = true;
|
||||
subdomain = "uptime";
|
||||
exposure = "local";
|
||||
port = 3001;
|
||||
homepage = {
|
||||
name = "Uptime Kuma";
|
||||
description = "Service monitoring tool";
|
||||
icon = "uptime-kuma.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
gitea = {
|
||||
enable = true;
|
||||
subdomain = "git";
|
||||
exposure = "tunnel";
|
||||
port = 5003;
|
||||
cloudflared = {
|
||||
tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
|
||||
credentialsFile = config.age.secrets.giteaCloudflared.path;
|
||||
};
|
||||
homepage = {
|
||||
name = "Gitea";
|
||||
description = "Git with a cup of tea";
|
||||
icon = "gitea.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
vaultwarden = {
|
||||
enable = true;
|
||||
subdomain = "vault";
|
||||
exposure = "tunnel";
|
||||
port = 8222;
|
||||
cloudflared = {
|
||||
tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
||||
credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
||||
};
|
||||
homepage = {
|
||||
name = "Vaultwarden";
|
||||
description = "Password manager";
|
||||
icon = "vaultwarden-light.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
nextcloud = {
|
||||
enable = true;
|
||||
subdomain = "cloud";
|
||||
exposure = "local";
|
||||
port = 8182;
|
||||
homepage = {
|
||||
name = "Nextcloud";
|
||||
description = "A safe home for all your data";
|
||||
icon = "nextcloud.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
qbittorrent = {
|
||||
enable = true;
|
||||
subdomain = "qbt";
|
||||
exposure = "local";
|
||||
port = 8080;
|
||||
homepage = {
|
||||
name = "qBittorrent";
|
||||
description = "Torrent client";
|
||||
icon = "qbittorrent.svg";
|
||||
category = "Downloads";
|
||||
};
|
||||
};
|
||||
slskd = {
|
||||
enable = true;
|
||||
subdomain = "slskd";
|
||||
exposure = "local";
|
||||
port = 5030;
|
||||
homepage = {
|
||||
name = "Soulseek";
|
||||
description = "Web-based Soulseek client";
|
||||
icon = "slskd.svg";
|
||||
category = "Downloads";
|
||||
};
|
||||
};
|
||||
pihole = {
|
||||
enable = true;
|
||||
subdomain = "pihole";
|
||||
exposure = "local";
|
||||
port = 8053;
|
||||
homepage = {
|
||||
name = "PiHole";
|
||||
description = "Adblocking and DNS service";
|
||||
icon = "pi-hole.svg";
|
||||
category = "Services";
|
||||
path = "/admin";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
username = "cnst";
|
||||
mail = "adam@cnst.dev";
|
||||
sshUser = "sobotka";
|
||||
domains = {
|
||||
local = "cnix.dev";
|
||||
public = "cnst.dev";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
name = "DVI-D-1";
|
||||
width = 1920;
|
||||
height = 1080;
|
||||
refreshRate = 144;
|
||||
refreshRate = "144";
|
||||
position = "0x0";
|
||||
transform = 0;
|
||||
workspace = "1";
|
||||
|
||||
26
lib/server/default.nix
Normal file
26
lib/server/default.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{lib}: let
|
||||
server = {
|
||||
mkDomain = config: service: let
|
||||
localDomain = config.settings.accounts.domains.local;
|
||||
publicDomain = config.settings.accounts.domains.public;
|
||||
tailscaleDomain = "ts.${publicDomain}";
|
||||
in
|
||||
if service.exposure == "tunnel"
|
||||
then publicDomain
|
||||
else if service.exposure == "tailscale"
|
||||
then tailscaleDomain
|
||||
else localDomain;
|
||||
|
||||
mkFullDomain = config: service: let
|
||||
domain = server.mkDomain config service;
|
||||
in "${service.subdomain}.${domain}";
|
||||
|
||||
mkHostDomain = config: service: let
|
||||
domain = server.mkDomain config service;
|
||||
in "${domain}";
|
||||
|
||||
mkSubDomain = config: service: "${service.subdomain}";
|
||||
};
|
||||
in {
|
||||
server = server;
|
||||
}
|
||||
@@ -123,28 +123,6 @@
|
||||
server = {
|
||||
imports = [
|
||||
./server
|
||||
./server/fail2ban
|
||||
./server/homepage-dashboard
|
||||
./server/nextcloud
|
||||
./server/vaultwarden
|
||||
./server/bazarr
|
||||
./server/prowlarr
|
||||
./server/lidarr
|
||||
./server/radarr
|
||||
./server/sonarr
|
||||
./server/jellyseerr
|
||||
./server/jellyfin
|
||||
./server/n8n
|
||||
./server/podman
|
||||
./server/unbound
|
||||
./server/uptime-kuma
|
||||
./server/keepalived
|
||||
./server/gitea
|
||||
./server/postgres
|
||||
./server/traefik
|
||||
./server/www
|
||||
./server/authentik
|
||||
./server/tailscale
|
||||
];
|
||||
};
|
||||
settings = {
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf mkEnableOption;
|
||||
inherit (lib.meta) getExe;
|
||||
inherit (pkgs) eza bat;
|
||||
packageNames = map (p: p.pname or p.name or null) config.home.packages;
|
||||
hasPackage = name: lib.any (x: x == name) packageNames;
|
||||
hasEza = hasPackage "eza";
|
||||
cfg = config.home.programs.fish;
|
||||
in
|
||||
{
|
||||
@@ -28,7 +29,9 @@ in
|
||||
nixclean = "nh clean all --keep 3";
|
||||
nixdev = "nix develop ~/.nix-config -c $SHELL";
|
||||
nixup = "nh os switch -H $hostname";
|
||||
nixupv = "nh os switch -v -H $hostname";
|
||||
nixupn = "nh os switch -n -H $hostname";
|
||||
nixupv = "nh os switch -v --show-trace -H $hostname";
|
||||
nixupvn = "nh os switch -n -v --show-trace -H $hostname";
|
||||
flakeup = "nix flake update";
|
||||
};
|
||||
shellAliases = {
|
||||
@@ -44,12 +47,8 @@ in
|
||||
nset = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/settings.nix";
|
||||
nixosmodules = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||
nmod = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||
tree = "${getExe eza} --tree --icons=always";
|
||||
cat = "${getExe bat} --style=plain";
|
||||
ls = "${getExe eza} -h --git --icons --color=auto --group-directories-first -s extension";
|
||||
ll = "${getExe eza} -l --git --icons --color=auto --group-directories-first -s extension";
|
||||
lat = "${getExe eza} -lah --tree --color=auto --group-directories-first -s extension";
|
||||
la = "${getExe eza} -lah --color=auto --group-directories-first -s extension";
|
||||
ls = mkIf hasEza "eza";
|
||||
tree = mkIf hasEza "eza --tree --icons=always";
|
||||
# Clear screen and scrollback
|
||||
clear = "printf '\\033[2J\\033[3J\\033[1;1H'";
|
||||
};
|
||||
@@ -59,14 +58,12 @@ in
|
||||
# Merge history when pressing up
|
||||
up-or-search = lib.readFile ./up-or-search.fish;
|
||||
# Check stuff in PATH
|
||||
nix-inspect =
|
||||
# fish
|
||||
nix-inspect = # fish
|
||||
''
|
||||
set -s PATH | grep "PATH\[.*/nix/store" | cut -d '|' -f2 | grep -v -e "-man" -e "-terminfo" | perl -pe 's:^/nix/store/\w{32}-([^/]*)/bin$:\1:' | sort | uniq
|
||||
'';
|
||||
};
|
||||
interactiveShellInit =
|
||||
# fish
|
||||
interactiveShellInit = # fish
|
||||
''
|
||||
# Open command buffer in vim when alt+e is pressed
|
||||
bind \ee edit_command_buffer
|
||||
|
||||
@@ -15,17 +15,16 @@ in
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = [ pkgs.gh ];
|
||||
programs.git = {
|
||||
programs = {
|
||||
git = {
|
||||
enable = true;
|
||||
userName = osConfig.settings.accounts.username;
|
||||
userEmail = osConfig.settings.accounts.mail;
|
||||
delta = {
|
||||
enable = true;
|
||||
options.dark = true;
|
||||
};
|
||||
extraConfig = {
|
||||
settings = {
|
||||
# user.signingkey = "${config.home.homeDirectory}/.ssh/id_ed25519.pub";
|
||||
user.signingkey = "${config.home.homeDirectory}/.config/git/allowed_signers";
|
||||
user = {
|
||||
name = osConfig.settings.accounts.username;
|
||||
email = osConfig.settings.accounts.mail;
|
||||
signingkey = "${config.home.homeDirectory}/.config/git/allowed_signers";
|
||||
};
|
||||
signing = {
|
||||
format = lib.mkDefault "ssh";
|
||||
key = "${config.home.homeDirectory}/.ssh/id_ed25519";
|
||||
@@ -56,6 +55,14 @@ in
|
||||
".jj"
|
||||
];
|
||||
};
|
||||
|
||||
delta = {
|
||||
enableGitIntegration = true;
|
||||
enable = true;
|
||||
options.dark = true;
|
||||
};
|
||||
};
|
||||
|
||||
xdg.configFile."git/allowed_signers".text = ''
|
||||
${osConfig.settings.accounts.mail} namespaces="git" ${osConfig.settings.accounts.sshKey}
|
||||
'';
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
lib,
|
||||
osConfig,
|
||||
cLib,
|
||||
clib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf mkEnableOption;
|
||||
inherit (lib) mkIf;
|
||||
cfg = osConfig.nixos.programs.hyprland;
|
||||
|
||||
hyprlockFlake = inputs.hyprlock.packages.${pkgs.system}.hyprlock;
|
||||
# hyprlockPkg = pkgs.hyprlock;
|
||||
#
|
||||
bg = osConfig.settings.theme.background;
|
||||
inherit (cLib.theme.bgs) resolve;
|
||||
inherit (clib.theme.bgs) resolve;
|
||||
in
|
||||
{
|
||||
config = mkIf cfg.enable {
|
||||
programs.hyprlock = {
|
||||
enable = true;
|
||||
package = hyprlockFlake;
|
||||
settings = {
|
||||
general = {
|
||||
# disable_loading_bar = true;
|
||||
@@ -60,6 +54,7 @@ in
|
||||
position = "0, 20";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
font_family = "DepartureMono Nerd Font Mono Italic";
|
||||
}
|
||||
];
|
||||
label = [
|
||||
@@ -71,7 +66,7 @@ in
|
||||
shadow_boost = 0.5;
|
||||
color = "rgba(FFFFFFFF)";
|
||||
font_size = 25;
|
||||
font_family = "Input Mono Compressed";
|
||||
font_family = "DepartureMono Nerd Font Mono Regular";
|
||||
position = "0, 230";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
@@ -84,7 +79,7 @@ in
|
||||
shadow_boost = 0.5;
|
||||
color = "rgba(FFFFFFFF)";
|
||||
font_size = 85;
|
||||
font_family = "Input Mono Compressed";
|
||||
font_family = "DepartureMono Nerd Font Mono Regular";
|
||||
position = "0, 300";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
|
||||
@@ -62,16 +62,8 @@ in
|
||||
[
|
||||
cmatrix
|
||||
xcur2png
|
||||
ripgrep
|
||||
file
|
||||
fd
|
||||
gnused
|
||||
nix-tree
|
||||
wireguard-tools
|
||||
unzip
|
||||
zip
|
||||
gnutar
|
||||
p7zip
|
||||
]
|
||||
|
||||
(mkIf cfg.common.enable [
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"group/system"
|
||||
],
|
||||
"modules-center": [
|
||||
"niri/workspaces"
|
||||
"hyprland/workspaces"
|
||||
],
|
||||
"modules-right": [
|
||||
"custom/progress",
|
||||
@@ -126,16 +126,28 @@
|
||||
"all-outputs": false,
|
||||
"format": "{icon}",
|
||||
"format-icons": {
|
||||
"urgent": "",
|
||||
"visible": "",
|
||||
"empty": ""
|
||||
"1": "1",
|
||||
"2": "2",
|
||||
"3": "3",
|
||||
"4": "4",
|
||||
"5": "5",
|
||||
"6": "6",
|
||||
"7": "7",
|
||||
"8": "8",
|
||||
"9": "9",
|
||||
"default": "_",
|
||||
"active": "_"
|
||||
},
|
||||
"on-click": "activate",
|
||||
"show-special": false,
|
||||
"on-scroll-up": "hyprctl dispatch workspace r-1",
|
||||
"on-scroll-down": "hyprctl dispatch workspace r+1",
|
||||
"persistent-workspaces": {
|
||||
"*": 3
|
||||
"1": [],
|
||||
"2": [],
|
||||
"3": [],
|
||||
"4": [],
|
||||
"5": []
|
||||
}
|
||||
},
|
||||
"niri/workspaces": {
|
||||
|
||||
@@ -28,8 +28,8 @@ tooltip label {
|
||||
margin: 0 0px;
|
||||
background-color: transparent;
|
||||
color: #fbf1c7;
|
||||
border-top: 3px solid transparent;
|
||||
border-bottom: 3px solid transparent;
|
||||
border-top: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
}
|
||||
|
||||
#workspaces button:hover {
|
||||
@@ -45,7 +45,7 @@ tooltip label {
|
||||
background-image: url("assets/button.svg");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 18px 15px;
|
||||
background-size: 21px 18px;
|
||||
}
|
||||
|
||||
#custom-trayicon {
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
{
|
||||
osConfig,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
cfg = osConfig.nixos.programs.hyprland;
|
||||
|
||||
hypridleFlake = inputs.hypridle.packages.${pkgs.system}.hypridle;
|
||||
# hypridlePkg = pkgs.hypridle;
|
||||
in
|
||||
{
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
services.hypridle = {
|
||||
enable = true;
|
||||
package = hypridleFlake;
|
||||
settings = {
|
||||
general = {
|
||||
lock_cmd = "hyprlock";
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
osConfig,
|
||||
cLib,
|
||||
clib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = osConfig.nixos.programs.hyprland;
|
||||
hyprpaperFlake = inputs.hyprpaper.packages.${pkgs.system}.default;
|
||||
bg = osConfig.settings.theme.background;
|
||||
bgs = cLib.theme.bgs;
|
||||
bgs = clib.theme.bgs;
|
||||
|
||||
monitorMappings = [
|
||||
{
|
||||
@@ -32,12 +28,10 @@ let
|
||||
bg = bg.primary;
|
||||
}
|
||||
];
|
||||
in
|
||||
{
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
services.hyprpaper = {
|
||||
enable = true;
|
||||
package = hyprpaperFlake;
|
||||
|
||||
settings = {
|
||||
ipc = "on";
|
||||
|
||||
@@ -19,13 +19,13 @@ let
|
||||
|
||||
commonPackages = with pkgs; [
|
||||
libva
|
||||
vaapiVdpau
|
||||
libva-vdpau-driver
|
||||
libvdpau-va-gl
|
||||
];
|
||||
|
||||
commonPackages32 = with pkgs.pkgsi686Linux; [
|
||||
libva
|
||||
vaapiVdpau
|
||||
libva-vdpau-driver
|
||||
libvdpau-va-gl
|
||||
];
|
||||
|
||||
|
||||
@@ -3,14 +3,11 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.meta) getExe;
|
||||
inherit (pkgs) eza bat;
|
||||
}: let
|
||||
inherit (lib) mkIf mkEnableOption mkMerge;
|
||||
|
||||
cfg = config.nixos.programs.fish;
|
||||
in
|
||||
{
|
||||
in {
|
||||
options = {
|
||||
nixos.programs.fish = {
|
||||
enable = mkEnableOption "Enables fish shell";
|
||||
@@ -22,6 +19,7 @@ in
|
||||
(mkIf cfg.enable {
|
||||
programs.fish = {
|
||||
enable = true;
|
||||
useBabelfish = true;
|
||||
vendor = {
|
||||
completions.enable = true;
|
||||
config.enable = true;
|
||||
@@ -37,7 +35,9 @@ in
|
||||
nixclean = "nh clean all --keep 3";
|
||||
nixdev = "nix develop ~/.nix-config -c $SHELL";
|
||||
nixup = "nh os switch -H $hostname";
|
||||
nixupv = "nh os switch -v -H $hostname";
|
||||
nixupn = "nh os switch -n -H $hostname";
|
||||
nixupv = "nh os switch -v --show-trace -H $hostname";
|
||||
nixupvn = "nh os switch -n -v --show-trace -H $hostname";
|
||||
flakeup = "nix flake update";
|
||||
};
|
||||
shellAliases = {
|
||||
@@ -53,12 +53,8 @@ in
|
||||
nset = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/settings.nix";
|
||||
nixosmodules = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||
nmod = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||
tree = "${getExe eza} --tree --icons=always";
|
||||
cat = "${getExe bat} --style=plain";
|
||||
ls = "${getExe eza} -h --git --icons --color=auto --group-directories-first -s extension";
|
||||
ll = "${getExe eza} -l --git --icons --color=auto --group-directories-first -s extension";
|
||||
lat = "${getExe eza} -lah --tree --color=auto --group-directories-first -s extension";
|
||||
la = "${getExe eza} -lah --color=auto --group-directories-first -s extension";
|
||||
ls = lib.getExe pkgs.eza;
|
||||
tree = "${lib.getExe pkgs.eza} --tree --icons=always";
|
||||
# Clear screen and scrollback
|
||||
clear = "printf '\\033[2J\\033[3J\\033[1;1H'";
|
||||
};
|
||||
|
||||
@@ -37,9 +37,9 @@ in
|
||||
};
|
||||
|
||||
gestures = {
|
||||
workspace_swipe = true;
|
||||
# workspace_swipe = true;
|
||||
workspace_swipe_distance = 400;
|
||||
workspace_swipe_fingers = 3;
|
||||
# workspace_swipe_fingers = 3;
|
||||
workspace_swipe_cancel_ratio = 0.2;
|
||||
workspace_swipe_min_speed_to_force = 5;
|
||||
workspace_swipe_direction_lock = true;
|
||||
|
||||
@@ -49,20 +49,6 @@ in
|
||||
"$mod, P, pseudo,"
|
||||
"$mod, J, togglesplit,"
|
||||
"$mod, C, exec, hyprctl dispatch exec copyq toggle"
|
||||
"$mod, left, movefocus, l"
|
||||
"$mod, right, movefocus, r"
|
||||
"$mod, up, movefocus, u"
|
||||
"$mod, down, movefocus, d"
|
||||
"$mod, 1, workspace, 1"
|
||||
"$mod, 2, workspace, 2"
|
||||
"$mod, 3, workspace, 3"
|
||||
"$mod, 4, workspace, 4"
|
||||
"$mod, 5, workspace, 5"
|
||||
"$mod, 6, workspace, 6"
|
||||
"$mod, 7, workspace, 7"
|
||||
"$mod, 8, workspace, 8"
|
||||
"$mod, 9, workspace, 9"
|
||||
"$mod, 0, workspace, 10"
|
||||
"$mod SHIFT, 1, movetoworkspace, 1"
|
||||
"$mod SHIFT, 2, movetoworkspace, 2"
|
||||
"$mod SHIFT, 3, movetoworkspace, 3"
|
||||
@@ -75,6 +61,30 @@ in
|
||||
"$mod SHIFT, 0, movetoworkspace, 10"
|
||||
"CTRL SHIFT, Escape, exec, ${runOnce "resources"}"
|
||||
|
||||
"$mod, 1, workspace, 1"
|
||||
"$mod, 2, workspace, 2"
|
||||
"$mod, 3, workspace, 3"
|
||||
"$mod, 4, workspace, 4"
|
||||
"$mod, 5, workspace, 5"
|
||||
"$mod, 6, workspace, 6"
|
||||
"$mod, 7, workspace, 7"
|
||||
"$mod, 8, workspace, 8"
|
||||
"$mod, 9, workspace, 9"
|
||||
"$mod, 0, workspace, 10"
|
||||
|
||||
"$mod, left, movefocus, l"
|
||||
"$mod, right, movefocus, r"
|
||||
"$mod, up, movefocus, u"
|
||||
"$mod, down, movefocus, d"
|
||||
"$mod SHIFT, left, resizeactive, -20 0"
|
||||
"$mod SHIFT, right, resizeactive, 20 0"
|
||||
"$mod SHIFT, up, resizeactive, 0 -20"
|
||||
"$mod SHIFT, down, resizeactive, 0 20"
|
||||
"$mod CTRL, left, swapwindow, l"
|
||||
"$mod CTRL, right, swapwindow, r"
|
||||
"$mod CTRL, up, swapwindow, u"
|
||||
"$mod CTRL, down, swapwindow, d"
|
||||
|
||||
",XF86AudioLowerVolume, exec, volume-control.sh --dec"
|
||||
",XF86AudioRaiseVolume, exec, volume-control.sh --inc"
|
||||
",XF86AudioMute, exec, volume-control.sh --toggle"
|
||||
@@ -99,7 +109,7 @@ in
|
||||
|
||||
(mkIf (host == "kima") {
|
||||
programs.hyprland.settings = {
|
||||
"$terminal" = "ghostty";
|
||||
"$terminal" = "alacritty";
|
||||
"$browser" = "zen";
|
||||
"$browserinc" = "zen --private-window";
|
||||
"$mod" = "SUPER";
|
||||
@@ -111,7 +121,7 @@ in
|
||||
|
||||
(mkIf (host == "bunk") {
|
||||
programs.hyprland.settings = {
|
||||
"$terminal" = "foot";
|
||||
"$terminal" = "alacritty";
|
||||
"$browser" = "zen";
|
||||
"$browserinc" = "zen --private-window";
|
||||
"$mod" = "ALT_L";
|
||||
|
||||
@@ -21,7 +21,7 @@ in
|
||||
let
|
||||
resolution =
|
||||
if m.width != null && m.height != null then
|
||||
"${toString m.width}x${toString m.height}@${toString m.refreshRate}"
|
||||
"${toString m.width}x${toString m.height}@${m.refreshRate}"
|
||||
else
|
||||
"preferred";
|
||||
|
||||
|
||||
@@ -79,10 +79,16 @@ in
|
||||
xmrig
|
||||
ocl-icd
|
||||
dig
|
||||
unzip
|
||||
zip
|
||||
gnutar
|
||||
gnused
|
||||
p7zip
|
||||
ripgrep
|
||||
file
|
||||
]
|
||||
|
||||
(mkIf cfg.common.enable [
|
||||
qt6.full
|
||||
swappy
|
||||
wayfreeze
|
||||
imagemagick
|
||||
|
||||
@@ -28,7 +28,7 @@ in
|
||||
};
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
protonup
|
||||
protonup-ng
|
||||
wine
|
||||
winetricks
|
||||
wine-wayland
|
||||
|
||||
@@ -16,14 +16,10 @@ in
|
||||
services.kanata = {
|
||||
enable = true;
|
||||
package = pkgs.kanata-with-cmd;
|
||||
keyboards.hhkbse = {
|
||||
keyboards.default = {
|
||||
extraDefCfg = ''
|
||||
process-unmapped-keys yes
|
||||
'';
|
||||
devices = [
|
||||
"/dev/input/by-id/usb-PFU_Limited_HHKB-Hybrid-event-kbd"
|
||||
"/dev/input/event2"
|
||||
];
|
||||
config = builtins.readFile (./. + "/hhkbse.kbd");
|
||||
};
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
2 3 4 5 6 7 8 9 0 + ´ ' §
|
||||
e p ¨
|
||||
l ö ä
|
||||
-
|
||||
z x rmet
|
||||
)
|
||||
|
||||
@@ -25,13 +26,16 @@
|
||||
_ _ _ _ _ _ _ _ _ _ pgdn pgup del
|
||||
_ _ '
|
||||
_ _ _
|
||||
_
|
||||
_ _ @level3
|
||||
)
|
||||
|
||||
|
||||
(deflayer level3
|
||||
RA-2 RA-3 S-4 RA-5 S-¨ RA-7 RA-8 RA-9 RA-0 RA-+ ⇥ ⇤ S-'
|
||||
RA-5 ▲ RA-¨
|
||||
◀ ▼ ▶
|
||||
RA-<
|
||||
RA-S-z RA-S-x @level3
|
||||
)
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ in
|
||||
inputs.fonts.packages.${pkgs.system}.vcr-mono
|
||||
noto-fonts
|
||||
noto-fonts-cjk-sans
|
||||
noto-fonts-emoji
|
||||
noto-fonts-color-emoji
|
||||
liberation_ttf
|
||||
fira-code-symbols
|
||||
font-awesome
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "bazarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.${unit};
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${unit}.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Bazarr";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Subtitle manager";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "bazarr.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Arr";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
services.traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.bazarr.loadBalancer.servers = [{url = "http://127.0.0.1:${toString config.services.${unit}.listenPort}";}];
|
||||
routers = {
|
||||
bazarr = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "bazarr";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,101 +1,16 @@
|
||||
{
|
||||
self,
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
hardDrives = [
|
||||
"/dev/disk/by-label/data"
|
||||
];
|
||||
inherit (lib) mkOption types;
|
||||
cfg = config.server;
|
||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||
clib = import "${self}/lib/server" {inherit lib;};
|
||||
in {
|
||||
options.server = {
|
||||
enable = lib.mkEnableOption "The server services and configuration variables";
|
||||
email = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Email name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
domain = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Domain name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
user = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
User to run the server services as
|
||||
'';
|
||||
};
|
||||
group = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Group to run the server services as
|
||||
'';
|
||||
};
|
||||
uid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
UID to run the server services as
|
||||
'';
|
||||
};
|
||||
gid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
GID to run the server services as
|
||||
'';
|
||||
};
|
||||
timeZone = lib.mkOption {
|
||||
default = "Europe/Stockholm";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Time zone to be used for the server services
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users = {
|
||||
groups.${cfg.group} = {
|
||||
gid = cfg.gid;
|
||||
};
|
||||
users.${cfg.user} = {
|
||||
uid = cfg.uid;
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
extraGroups = ifTheyExist [
|
||||
"audio"
|
||||
"video"
|
||||
"docker"
|
||||
"libvirtd"
|
||||
"qemu-libvirtd"
|
||||
"rtkit"
|
||||
"fail2ban"
|
||||
"vaultwarden"
|
||||
"qbittorrent"
|
||||
"lidarr"
|
||||
"prowlarr"
|
||||
"bazarr"
|
||||
"sonarr"
|
||||
"radarr"
|
||||
"media"
|
||||
"share"
|
||||
"render"
|
||||
"input"
|
||||
"authentik"
|
||||
"traefik"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
imports = [
|
||||
{
|
||||
_module.args.clib = clib;
|
||||
}
|
||||
./options.nix
|
||||
./infra
|
||||
./services
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
# "inspired" by @jtojnar <3
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: 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.";
|
||||
};
|
||||
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 {
|
||||
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 {
|
||||
age.secrets = {
|
||||
giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age";
|
||||
};
|
||||
|
||||
server = {
|
||||
fail2ban = lib.mkIf config.server.fail2ban.enable {
|
||||
jails = {
|
||||
gitea = {
|
||||
serviceName = "gitea";
|
||||
failRegex = ''.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
cloudflared = {
|
||||
enable = true;
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${cfg.url}".service = "http://localhost:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
${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;
|
||||
};
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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 = [
|
||||
{
|
||||
database = "gitea";
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
unit = "homepage-dashboard";
|
||||
cfg = config.server.homepage-dashboard;
|
||||
srv = config.server;
|
||||
in {
|
||||
options.server.homepage-dashboard = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
misc = lib.mkOption {
|
||||
default = [];
|
||||
type = lib.types.listOf (
|
||||
lib.types.attrsOf (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
href = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
siteMonitor = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
homepageEnvironment = {
|
||||
file = "${self}/secrets/homepageEnvironment.age";
|
||||
};
|
||||
};
|
||||
services = {
|
||||
glances.enable = true;
|
||||
${unit} = {
|
||||
enable = true;
|
||||
environmentFile = config.age.secrets.homepageEnvironment.path;
|
||||
settings = {
|
||||
layout = [
|
||||
{
|
||||
Glances = {
|
||||
header = false;
|
||||
style = "row";
|
||||
columns = 4;
|
||||
};
|
||||
}
|
||||
{
|
||||
Arr = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
{
|
||||
Downloads = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
{
|
||||
Media = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
{
|
||||
Services = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
];
|
||||
headerStyle = "clean";
|
||||
statusStyle = "dot";
|
||||
hideVersion = "true";
|
||||
};
|
||||
widgets = [
|
||||
{
|
||||
openmeteo = {
|
||||
label = "Kalmar";
|
||||
timezone = "Europe/Stockholm";
|
||||
units = "metric";
|
||||
cache = 5;
|
||||
latitude = 56.707262;
|
||||
longitude = 16.324541;
|
||||
};
|
||||
}
|
||||
{
|
||||
resources = {
|
||||
label = "SYSTEM";
|
||||
memory = true;
|
||||
cpu = true;
|
||||
uptime = false;
|
||||
};
|
||||
}
|
||||
];
|
||||
services = let
|
||||
homepageCategories = [
|
||||
"Arr"
|
||||
"Media"
|
||||
"Downloads"
|
||||
"Services"
|
||||
];
|
||||
hl = config.server;
|
||||
mergedServices = hl // hl.podman;
|
||||
homepageServices = x: (lib.attrsets.filterAttrs (
|
||||
name: value: value ? homepage && value.homepage.category == x
|
||||
)
|
||||
mergedServices);
|
||||
in
|
||||
lib.lists.forEach homepageCategories (cat: {
|
||||
"${cat}" =
|
||||
lib.lists.forEach
|
||||
(lib.attrsets.mapAttrsToList (name: value: {
|
||||
inherit name;
|
||||
url = value.url;
|
||||
homepage = value.homepage;
|
||||
}) (homepageServices "${cat}"))
|
||||
(x: {
|
||||
"${x.homepage.name}" = {
|
||||
icon = x.homepage.icon;
|
||||
description = x.homepage.description;
|
||||
href = "https://${x.url}${x.homepage.path or ""}";
|
||||
siteMonitor = "https://${x.url}${x.homepage.path or ""}";
|
||||
};
|
||||
});
|
||||
})
|
||||
++ [{Misc = cfg.misc;}]
|
||||
++ [
|
||||
{
|
||||
Glances = let
|
||||
port = toString config.services.glances.port;
|
||||
in [
|
||||
{
|
||||
Info = {
|
||||
widget = {
|
||||
type = "glances";
|
||||
url = "http://localhost:${port}";
|
||||
metric = "info";
|
||||
chart = false;
|
||||
version = 4;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"CPU Temp" = {
|
||||
widget = {
|
||||
type = "glances";
|
||||
url = "http://localhost:${port}";
|
||||
metric = "sensor:Tctl";
|
||||
chart = false;
|
||||
version = 4;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"GPU Radeon" = {
|
||||
widget = {
|
||||
type = "glances";
|
||||
url = "http://localhost:${port}";
|
||||
metric = "sensor:junction";
|
||||
chart = false;
|
||||
version = 4;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"GPU Intel" = {
|
||||
widget = {
|
||||
type = "glances";
|
||||
url = "http://localhost:${port}";
|
||||
metric = "sensor:pkg";
|
||||
chart = false;
|
||||
version = 4;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
Processes = {
|
||||
widget = {
|
||||
type = "glances";
|
||||
url = "http://localhost:${port}";
|
||||
metric = "process";
|
||||
chart = false;
|
||||
version = 4;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
Network = {
|
||||
widget = {
|
||||
type = "glances";
|
||||
url = "http://localhost:${port}";
|
||||
metric = "network:enp6s0";
|
||||
chart = false;
|
||||
version = 4;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
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"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,21 +1,24 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
unit = "authentik";
|
||||
cfg = config.server.${unit};
|
||||
srv = config.server;
|
||||
cfg = config.server.infra.${unit};
|
||||
srv = config.server.infra;
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
options.server.infra.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "auth.${srv.www.domain}";
|
||||
default = "auth.${srv.www.url}";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
description = "The local port the service runs on";
|
||||
};
|
||||
cloudflared = {
|
||||
credentialsFile = lib.mkOption {
|
||||
@@ -31,21 +34,11 @@ in {
|
||||
example = "00000000-0000-0000-0000-000000000000";
|
||||
};
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Authentik";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "An open-source IdP for modern SSO";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "authentik.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
homepage = {
|
||||
name = "Authentik";
|
||||
description = "An open-source IdP for modern SSO";
|
||||
icon = "authentik.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -59,8 +52,8 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
server = {
|
||||
fail2ban = lib.mkIf cfg.enable {
|
||||
server.infra = {
|
||||
fail2ban = {
|
||||
jails = {
|
||||
authentik = {
|
||||
serviceName = "authentik";
|
||||
13
modules/server/infra/default.nix
Normal file
13
modules/server/infra/default.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
imports = [
|
||||
./authentik
|
||||
./fail2ban
|
||||
./keepalived
|
||||
./podman
|
||||
./postgres
|
||||
./tailscale
|
||||
./traefik
|
||||
./unbound
|
||||
./www
|
||||
];
|
||||
}
|
||||
@@ -5,9 +5,9 @@
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.server.fail2ban;
|
||||
cfg = config.server.infra.fail2ban;
|
||||
in {
|
||||
options.server.fail2ban = {
|
||||
options.server.infra.fail2ban = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable cloudflare fail2ban";
|
||||
};
|
||||
@@ -61,6 +61,7 @@ in {
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
@@ -3,27 +3,24 @@
|
||||
config,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
let
|
||||
}: let
|
||||
unit = "keepalived";
|
||||
cfg = config.server.${unit};
|
||||
cfg = config.server.infra.${unit};
|
||||
|
||||
hostCfg =
|
||||
hostname:
|
||||
if hostname == "sobotka" then
|
||||
{
|
||||
hostCfg = hostname:
|
||||
if hostname == "sobotka"
|
||||
then {
|
||||
ip = "192.168.88.14";
|
||||
priority = 20;
|
||||
state = "MASTER";
|
||||
}
|
||||
else if hostname == "ziggy" then
|
||||
{
|
||||
else if hostname == "ziggy"
|
||||
then {
|
||||
ip = "192.168.88.12";
|
||||
priority = 10;
|
||||
state = "BACKUP";
|
||||
}
|
||||
else
|
||||
throw "No keepalived config defined for host ${hostname}";
|
||||
else throw "No keepalived config defined for host ${hostname}";
|
||||
|
||||
_self = hostCfg config.networking.hostName;
|
||||
|
||||
@@ -34,9 +31,8 @@ let
|
||||
|
||||
# Remove self from peers
|
||||
peers = builtins.filter (ip: ip != _self.ip) allPeers;
|
||||
in
|
||||
{
|
||||
options.server.${unit} = {
|
||||
in {
|
||||
options.server.infra.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
6
modules/server/infra/podman/acquis.yaml
Normal file
6
modules/server/infra/podman/acquis.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
filenames:
|
||||
- /var/log/traefik/access.log
|
||||
poll_without_inotify: true
|
||||
labels:
|
||||
type: traefik
|
||||
194
modules/server/infra/podman/default.nix
Normal file
194
modules/server/infra/podman/default.nix
Normal file
@@ -0,0 +1,194 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
infra = config.server.infra;
|
||||
cfg = config.server.services;
|
||||
|
||||
getPiholeSecret = hostname:
|
||||
if hostname == "ziggy"
|
||||
then [config.age.secrets.piholeZiggy.path]
|
||||
else if hostname == "sobotka"
|
||||
then [config.age.secrets.pihole.path]
|
||||
else throw "Unknown hostname: ${hostname}";
|
||||
in {
|
||||
options.server.infra = {
|
||||
podman.enable = lib.mkEnableOption "Enables Podman";
|
||||
gluetun.enable = lib.mkEnableOption "Enables gluetun";
|
||||
};
|
||||
config = lib.mkIf infra.podman.enable {
|
||||
age.secrets = {
|
||||
pihole.file = "${self}/secrets/${config.networking.hostName}Pihole.age";
|
||||
slskd.file = "${self}/secrets/slskd.age";
|
||||
};
|
||||
|
||||
virtualisation = {
|
||||
containers.enable = true;
|
||||
podman.enable = true;
|
||||
};
|
||||
|
||||
networking.firewall = lib.mkIf cfg.pihole.enable {
|
||||
allowedTCPPorts = [
|
||||
53
|
||||
5335
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
53
|
||||
5335
|
||||
];
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers = lib.mkMerge [
|
||||
(lib.mkIf infra.gluetun.enable {
|
||||
gluetun = {
|
||||
image = "qmcgaw/gluetun";
|
||||
ports = [
|
||||
"8388:8388"
|
||||
"58846:58846"
|
||||
"8080:8080"
|
||||
"5030:5030"
|
||||
"5031:5031"
|
||||
"50300:50300"
|
||||
];
|
||||
devices = ["/dev/net/tun:/dev/net/tun"];
|
||||
autoStart = true;
|
||||
extraOptions = [
|
||||
"--cap-add=NET_ADMIN"
|
||||
];
|
||||
volumes = ["/var:/gluetun"];
|
||||
environmentFiles = [
|
||||
config.age.secrets.gluetunEnvironment.path
|
||||
];
|
||||
environment = {
|
||||
DEV_MODE = "false";
|
||||
VPN_SERVICE_PROVIDER = "mullvad";
|
||||
VPN_TYPE = "wireguard";
|
||||
SERVER_CITIES = "Stockholm";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.qbittorrent.enable {
|
||||
qbittorrent = {
|
||||
image = "ghcr.io/hotio/qbittorrent:latest";
|
||||
autoStart = true;
|
||||
dependsOn = ["gluetun"];
|
||||
ports = [
|
||||
"8080:8080"
|
||||
"58846:58846"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=container:gluetun"
|
||||
];
|
||||
volumes = [
|
||||
"/var/lib/qbittorrent:/config:rw"
|
||||
"/mnt/data/media/downloads:/downloads:rw"
|
||||
];
|
||||
environmentFiles = [
|
||||
config.age.secrets.gluetunEnvironment.path
|
||||
];
|
||||
environment = {
|
||||
PUID = "994";
|
||||
PGID = "993";
|
||||
TZ = "Europe/Stockholm";
|
||||
WEBUI_PORT = "${builtins.toString cfg.qbittorrent.port}";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.slskd.enable {
|
||||
slskd = {
|
||||
image = "slskd/slskd:latest";
|
||||
autoStart = true;
|
||||
dependsOn = ["gluetun"];
|
||||
ports = [
|
||||
"5030:5030"
|
||||
"5031:5031"
|
||||
"50300:50300"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=container:gluetun"
|
||||
];
|
||||
volumes = [
|
||||
"/var/lib/slskd:/app:rw"
|
||||
"/mnt/data/media/downloads:/downloads:rw"
|
||||
];
|
||||
environmentFiles = [
|
||||
config.age.secrets.gluetunEnvironment.path
|
||||
config.age.secrets.slskd.path
|
||||
];
|
||||
environment = {
|
||||
TZ = "Europe/Stockholm";
|
||||
PUID = "981";
|
||||
PGID = "982";
|
||||
SLSKD_REMOTE_CONFIGURATION = "true";
|
||||
SLSKD_REMOTE_FILE_MANAGEMENT = "true";
|
||||
SLSKD_DOWNLOADS_DIR = "/downloads";
|
||||
SLSKD_UMASK = "022";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.pihole.enable {
|
||||
pihole = {
|
||||
autoStart = true;
|
||||
image = "pihole/pihole:2025.08.0";
|
||||
volumes = [
|
||||
"/var/lib/pihole:/etc/pihole/"
|
||||
"/var/lib/dnsmasq.d:/etc/dnsmasq.d/"
|
||||
];
|
||||
environment = {
|
||||
TZ = "Europe/Stockholm";
|
||||
CUSTOM_CACHE_SIZE = "0";
|
||||
WEBTHEME = "default-darker";
|
||||
};
|
||||
environmentFiles = getPiholeSecret config.networking.hostName;
|
||||
ports = [
|
||||
"53:53/tcp"
|
||||
"53:53/udp"
|
||||
"8053:80/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--cap-add=NET_ADMIN"
|
||||
"--cap-add=SYS_NICE"
|
||||
"--cap-add=SYS_TIME"
|
||||
];
|
||||
};
|
||||
})
|
||||
(lib.mkIf cfg.ollama.enable {
|
||||
intel-llm = {
|
||||
autoStart = true;
|
||||
image = "intelanalytics/ipex-llm-inference-cpp-xpu:latest";
|
||||
devices = [
|
||||
"/dev/dri:/dev/dri:rwm"
|
||||
];
|
||||
volumes = [
|
||||
"/var/lib/ollama:/models"
|
||||
];
|
||||
environment = {
|
||||
OLLAMA_ORIGINS = "http://192.168.*";
|
||||
SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS = "1";
|
||||
ONEAPI_DEVICE_SELECTOR = "level_zero:0";
|
||||
OLLAMA_HOST = "[::]:11434";
|
||||
no_proxy = "localhost,127.0.0.1";
|
||||
DEVICE = "Arc";
|
||||
OLLAMA_NUM_GPU = "999";
|
||||
ZES_ENABLE_SYSMAN = "1";
|
||||
};
|
||||
cmd = [
|
||||
"/bin/sh"
|
||||
"-c"
|
||||
"/llm/scripts/start-ollama.sh && echo 'Startup script finished, container is now idling.' && sleep infinity"
|
||||
];
|
||||
extraOptions = [
|
||||
"--net=host"
|
||||
"--memory=32G"
|
||||
"--shm-size=16g"
|
||||
];
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -7,10 +7,10 @@
|
||||
}: let
|
||||
inherit (lib) types mkOption;
|
||||
|
||||
cfg = config.server.postgresql;
|
||||
cfg = config.server.infra.postgresql;
|
||||
in {
|
||||
options = {
|
||||
server.postgresql = {
|
||||
server.infra.postgresql = {
|
||||
upgradeTargetPackage = mkOption {
|
||||
type = types.nullOr types.package;
|
||||
default = null;
|
||||
@@ -7,7 +7,7 @@
|
||||
}: let
|
||||
inherit (lib) types mkOption;
|
||||
|
||||
cfg = config.server.postgresql;
|
||||
cfg = config.server.infra.postgresql;
|
||||
|
||||
database = {name, ...}: {
|
||||
options = {
|
||||
@@ -31,7 +31,7 @@
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
server.postgresql = {
|
||||
server.infra.postgresql = {
|
||||
databases = mkOption {
|
||||
type = types.listOf (types.submodule database);
|
||||
default = [];
|
||||
@@ -5,16 +5,11 @@
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.server.tailscale;
|
||||
cfg = config.server.infra.tailscale;
|
||||
in {
|
||||
options.server.tailscale = {
|
||||
options.server.infra.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";
|
||||
|
||||
183
modules/server/infra/traefik/default.nix
Normal file
183
modules/server/infra/traefik/default.nix
Normal file
@@ -0,0 +1,183 @@
|
||||
{
|
||||
lib,
|
||||
clib,
|
||||
config,
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkEnableOption mkIf types;
|
||||
|
||||
cfg = config.server.infra.traefik;
|
||||
srv = config.server;
|
||||
|
||||
generateRouters = services: config:
|
||||
lib.mapAttrs' (
|
||||
name: service:
|
||||
lib.nameValuePair name {
|
||||
entryPoints = ["websecure"];
|
||||
# FIX 3: Use backticks for the Host rule and interpolation
|
||||
rule = "Host(`${clib.server.mkFullDomain config service}`)";
|
||||
service = name;
|
||||
tls.certResolver = "letsencrypt";
|
||||
}
|
||||
) (lib.filterAttrs (_: s: s.enable) services);
|
||||
|
||||
generateServices = services:
|
||||
lib.mapAttrs' (name: service:
|
||||
lib.nameValuePair name {
|
||||
loadBalancer.servers = [{url = "http://localhost:${toString service.port}";}];
|
||||
}) (lib.filterAttrs (name: service: service.enable) services);
|
||||
|
||||
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.infra.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";
|
||||
};
|
||||
crowdsecApi.file = "${self}/secrets/crowdsecApi.age";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
accesslog = {filepath = "/var/lib/traefik/logs/access.log";};
|
||||
|
||||
tracing = {};
|
||||
api = {
|
||||
dashboard = true;
|
||||
insecure = false;
|
||||
};
|
||||
|
||||
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 = ":80";
|
||||
forwardedHeaders.insecure = true;
|
||||
http.redirections.entryPoint = {
|
||||
to = "websecure";
|
||||
scheme = "https";
|
||||
permanent = true;
|
||||
};
|
||||
# http.middlewares = "crowdsec@file";
|
||||
};
|
||||
|
||||
websecure = {
|
||||
address = ":443";
|
||||
forwardedHeaders.insecure = true;
|
||||
http.tls = {
|
||||
certResolver = "letsencrypt";
|
||||
domains = [
|
||||
{
|
||||
main = "cnix.dev";
|
||||
sans = ["*.cnix.dev"];
|
||||
}
|
||||
{
|
||||
main = "ts.cnst.dev";
|
||||
sans = ["*ts.cnst.dev"];
|
||||
}
|
||||
];
|
||||
};
|
||||
# http.middlewares = "crowdsec@file";
|
||||
};
|
||||
|
||||
experimental = {
|
||||
address = ":1111";
|
||||
forwardedHeaders.insecure = true;
|
||||
};
|
||||
};
|
||||
|
||||
experimental = {
|
||||
# Install the Crowdsec Bouncer plugin
|
||||
plugins = {
|
||||
#enabled = "true";
|
||||
bouncer = {
|
||||
moduleName = "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin";
|
||||
version = "v1.4.5";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services = generateServices srv.services;
|
||||
|
||||
routers =
|
||||
(generateRouters srv.services config)
|
||||
// {
|
||||
api = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`traefik.${srv.domain}`)";
|
||||
service = "api@internal";
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
};
|
||||
# middlewares = {
|
||||
# crowdsec = {
|
||||
# plugin = {
|
||||
# bouncer = {
|
||||
# enabled = "true";
|
||||
# logLevel = "DEBUG";
|
||||
# crowdsecLapiKeyFile = config.age.secrets.crowdsecApi.path;
|
||||
# crowdsecMode = "live";
|
||||
# crowdsecLapiHost = ":4223";
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -5,7 +5,20 @@
|
||||
...
|
||||
}: let
|
||||
unit = "unbound";
|
||||
cfg = config.server.${unit};
|
||||
cfg = config.server.infra.${unit};
|
||||
srv = config.server;
|
||||
|
||||
svcNames = lib.attrNames srv.services;
|
||||
|
||||
localARecords = builtins.concatLists (map (
|
||||
name: let
|
||||
s = srv.services.${name};
|
||||
in
|
||||
if s != null && s.enable && s.subdomain != null
|
||||
then [''"${s.subdomain}.${srv.domain}. A ${srv.ip}"'']
|
||||
else []
|
||||
)
|
||||
svcNames);
|
||||
|
||||
hostIp = hostname:
|
||||
if hostname == "ziggy"
|
||||
@@ -14,11 +27,12 @@
|
||||
then "192.168.88.14"
|
||||
else throw "No IP defined for host ${hostname}";
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
options.server.infra.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
# resolved.enable = lib.mkForce false;
|
||||
@@ -97,6 +111,11 @@ in {
|
||||
"255.255.255.255/32"
|
||||
"2001:db8::/32"
|
||||
];
|
||||
local-data =
|
||||
[
|
||||
''"traefik.${config.settings.accounts.domains.local}. A 192.168.88.14"''
|
||||
]
|
||||
++ localARecords;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption mkEnableOption mkIf types;
|
||||
cfg = config.server.www;
|
||||
srv = config.server;
|
||||
inherit (lib) mkIf mkEnableOption mkOption types;
|
||||
cfg = config.server.infra.www;
|
||||
in {
|
||||
options.server.www = {
|
||||
options.server.infra.www = {
|
||||
enable = mkEnableOption {
|
||||
description = "Enable personal website";
|
||||
};
|
||||
@@ -20,6 +18,12 @@ in {
|
||||
Public domain name to be used to access the server services via Traefik reverse proxy
|
||||
'';
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 8283;
|
||||
description = "The port to host webservice on.";
|
||||
};
|
||||
|
||||
cloudflared = {
|
||||
credentialsFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
@@ -41,8 +45,8 @@ in {
|
||||
wwwCloudflared.file = "${self}/secrets/wwwCloudflared.age";
|
||||
};
|
||||
|
||||
server = {
|
||||
fail2ban = lib.mkIf config.server.www.enable {
|
||||
server.infra = {
|
||||
fail2ban = {
|
||||
jails = {
|
||||
nginx-404 = {
|
||||
serviceName = "nginx";
|
||||
@@ -1,65 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
unit = "jellyfin";
|
||||
cfg = config.server.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "fin.${srv.tailscale.url}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Jellyfin";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "The Free Software Media System";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "jellyfin.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Media";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
jellyfin-ffmpeg
|
||||
];
|
||||
services.traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.${unit}.loadBalancer.servers = [{url = "http://localhost:8096";}];
|
||||
routers = {
|
||||
jellyfinRouter = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "${unit}";
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "jellyseerr";
|
||||
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 = "seer.${srv.tailscale.url}";
|
||||
default = "jellyseerr.${srv.domain}";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 5055;
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Jellyseerr";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Media request and discovery manager";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "jellyseerr.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Arr";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
port = cfg.port;
|
||||
};
|
||||
services.traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.jellyseerr.loadBalancer.servers = [{url = "http://localhost:${toString cfg.port}";}];
|
||||
routers = {
|
||||
jellyseerr = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "${unit}";
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "lidarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.${unit};
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${unit}.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Lidarr";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Music collection manager";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "lidarr.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Arr";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
services.traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.lidarr.loadBalancer.servers = [{url = "http://127.0.0.1:8686";}];
|
||||
routers = {
|
||||
lidarr = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "lidarr";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "n8n";
|
||||
srv = config.server;
|
||||
cfg = config.server.${unit};
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${unit}.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "n8n";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "A workflow automation platform";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "n8n.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
n8n = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.n8n.loadBalancer.servers = [{url = "http://127.0.0.1:5678";}];
|
||||
routers = {
|
||||
n8n = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "n8n";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
unit = "nextcloud";
|
||||
cfg = config.server.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
adminpassFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
};
|
||||
adminuser = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "cnst";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "cloud.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Nextcloud";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "A safe home for all your data";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nextcloud.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
};
|
||||
};
|
||||
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 {
|
||||
jails = {
|
||||
nextcloud = {
|
||||
serviceName = "${unit}";
|
||||
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
||||
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)?"'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
${unit} = {
|
||||
enable = true;
|
||||
package = pkgs.nextcloud32;
|
||||
hostName = "nextcloud";
|
||||
configureRedis = true;
|
||||
caching = {
|
||||
redis = true;
|
||||
};
|
||||
phpOptions = {
|
||||
"opcache.interned_strings_buffer" = "32";
|
||||
};
|
||||
maxUploadSize = "50G";
|
||||
settings = {
|
||||
maintenance_window_start = "1";
|
||||
trusted_proxies = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
trusted_domains = ["cloud.${srv.domain}"];
|
||||
overwriteprotocol = "https";
|
||||
enabledPreviewProviders = [
|
||||
"OC\\Preview\\BMP"
|
||||
"OC\\Preview\\GIF"
|
||||
"OC\\Preview\\JPEG"
|
||||
"OC\\Preview\\Krita"
|
||||
"OC\\Preview\\MarkDown"
|
||||
"OC\\Preview\\MP3"
|
||||
"OC\\Preview\\OpenDocument"
|
||||
"OC\\Preview\\PNG"
|
||||
"OC\\Preview\\TXT"
|
||||
"OC\\Preview\\XBitmap"
|
||||
"OC\\Preview\\HEIC"
|
||||
];
|
||||
};
|
||||
config = {
|
||||
dbtype = "pgsql";
|
||||
dbuser = "nextcloud";
|
||||
dbhost = "/run/postgresql";
|
||||
dbname = "nextcloud";
|
||||
adminuser = "cnst";
|
||||
adminpassFile = cfg.adminpassFile;
|
||||
};
|
||||
};
|
||||
|
||||
nginx = {
|
||||
defaultListen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 8182;
|
||||
}
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 8482;
|
||||
}
|
||||
];
|
||||
virtualHosts.nextcloud = {
|
||||
forceSSL = false;
|
||||
};
|
||||
};
|
||||
|
||||
traefik.dynamicConfigOptions.http = {
|
||||
routers.nextcloud = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "nextcloud";
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
services.nextcloud.loadBalancer.servers = [
|
||||
{url = "http://127.0.0.1:8182";}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
server.postgresql.databases = [
|
||||
{
|
||||
database = "nextcloud";
|
||||
}
|
||||
];
|
||||
systemd.services."nextcloud-setup" = {
|
||||
requires = ["postgresql.service"];
|
||||
after = ["postgresql.service"];
|
||||
};
|
||||
};
|
||||
}
|
||||
180
modules/server/options.nix
Normal file
180
modules/server/options.nix
Normal file
@@ -0,0 +1,180 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption types;
|
||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||
cfg = config.server;
|
||||
in {
|
||||
options.server = {
|
||||
enable = lib.mkEnableOption "The server services and configuration variables";
|
||||
email = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Email name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
domain = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Domain name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
ip = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "The local IP of the service.";
|
||||
};
|
||||
user = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
User to run the server services as
|
||||
'';
|
||||
};
|
||||
group = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Group to run the server services as
|
||||
'';
|
||||
};
|
||||
uid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
UID to run the server services as
|
||||
'';
|
||||
};
|
||||
gid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
GID to run the server services as
|
||||
'';
|
||||
};
|
||||
timeZone = lib.mkOption {
|
||||
default = "Europe/Stockholm";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Time zone to be used for the server services
|
||||
'';
|
||||
};
|
||||
services = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "the service";
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "The subdomain for the service (e.g., 'jellyfin')";
|
||||
};
|
||||
exposure = lib.mkOption {
|
||||
type = lib.types.enum ["local" "tunnel" "tailscale"];
|
||||
default = "local";
|
||||
description = "Controls where the service is exposed";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 80;
|
||||
description = "The port to host service on.";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/${name}";
|
||||
description = "Configuration directory for ${name}.";
|
||||
};
|
||||
cloudflared = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
description = "Cloudflare tunnel configuration for this service.";
|
||||
};
|
||||
homepage = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Display name on the homepage.";
|
||||
};
|
||||
description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "A short description for the homepage tile.";
|
||||
};
|
||||
icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Zervices c00l stuff";
|
||||
description = "Icon file name for the homepage tile.";
|
||||
};
|
||||
category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Homepage category grouping.";
|
||||
};
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "/admin";
|
||||
description = "Optional path suffix for homepage links (e.g. /admin).";
|
||||
};
|
||||
};
|
||||
};
|
||||
description = "Homepage metadata for this service.";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
users = {
|
||||
groups.${cfg.group} = {
|
||||
gid = cfg.gid;
|
||||
};
|
||||
users.${cfg.user} = {
|
||||
uid = cfg.uid;
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
extraGroups = ifTheyExist [
|
||||
"audio"
|
||||
"video"
|
||||
"docker"
|
||||
"libvirtd"
|
||||
"qemu-libvirtd"
|
||||
"rtkit"
|
||||
"fail2ban"
|
||||
"vaultwarden"
|
||||
"qbittorrent"
|
||||
"lidarr"
|
||||
"prowlarr"
|
||||
"bazarr"
|
||||
"sonarr"
|
||||
"radarr"
|
||||
"media"
|
||||
"share"
|
||||
"render"
|
||||
"input"
|
||||
"authentik"
|
||||
"traefik"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
srv = config.server;
|
||||
cfg = config.server.podman;
|
||||
|
||||
piholeUrl =
|
||||
if config.networking.hostName == "sobotka"
|
||||
then "pihole0"
|
||||
else if config.networking.hostName == "ziggy"
|
||||
then "pihole1"
|
||||
else throw "Unknown hostname";
|
||||
|
||||
getPiholeSecret = hostname:
|
||||
if hostname == "ziggy"
|
||||
then [config.age.secrets.piholeZiggy.path]
|
||||
else if hostname == "sobotka"
|
||||
then [config.age.secrets.pihole.path]
|
||||
else throw "Unknown hostname: ${hostname}";
|
||||
in {
|
||||
options.server.podman = {
|
||||
enable = lib.mkEnableOption "Enables Podman";
|
||||
gluetun.enable = lib.mkEnableOption "Enables gluetun";
|
||||
|
||||
qbittorrent = {
|
||||
enable = lib.mkEnableOption "Enable qBittorrent";
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "qbt.${srv.domain}";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 8080;
|
||||
description = "The port to host qBittorrent on.";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "qBittorrent";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Torrent client";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "qbittorrent.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Downloads";
|
||||
};
|
||||
};
|
||||
|
||||
slskd = {
|
||||
enable = lib.mkEnableOption "Enable Soulseek";
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "slskd.${srv.domain}";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 5030;
|
||||
description = "The port to host Soulseek webui on.";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "slskd";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Web-based Soulseek client";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "slskd.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Downloads";
|
||||
};
|
||||
};
|
||||
|
||||
pihole = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 8053;
|
||||
description = "The port to host PiHole on.";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${piholeUrl}.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "PiHole";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Adblocking and DNS service";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "pi-hole.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
};
|
||||
homepage.path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/admin";
|
||||
description = "Optional path suffix for homepage links (e.g. /admin).";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
pihole.file = "${self}/secrets/${config.networking.hostName}Pihole.age";
|
||||
slskd.file = "${self}/secrets/slskd.age";
|
||||
};
|
||||
|
||||
virtualisation = {
|
||||
containers.enable = true;
|
||||
podman.enable = true;
|
||||
};
|
||||
|
||||
networking.firewall = lib.mkIf cfg.pihole.enable {
|
||||
allowedTCPPorts = [
|
||||
53
|
||||
5335
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
53
|
||||
5335
|
||||
];
|
||||
};
|
||||
|
||||
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 [
|
||||
(lib.mkIf cfg.gluetun.enable {
|
||||
gluetun = {
|
||||
image = "qmcgaw/gluetun";
|
||||
ports = [
|
||||
"8388:8388"
|
||||
"58846:58846"
|
||||
"8080:8080"
|
||||
"5030:5030"
|
||||
"5031:5031"
|
||||
"50300:50300"
|
||||
];
|
||||
devices = ["/dev/net/tun:/dev/net/tun"];
|
||||
autoStart = true;
|
||||
extraOptions = [
|
||||
"--cap-add=NET_ADMIN"
|
||||
];
|
||||
volumes = ["/var:/gluetun"];
|
||||
environmentFiles = [
|
||||
config.age.secrets.gluetunEnvironment.path
|
||||
];
|
||||
environment = {
|
||||
DEV_MODE = "false";
|
||||
VPN_SERVICE_PROVIDER = "mullvad";
|
||||
VPN_TYPE = "wireguard";
|
||||
SERVER_CITIES = "Stockholm";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.qbittorrent.enable {
|
||||
qbittorrent = {
|
||||
image = "ghcr.io/hotio/qbittorrent:latest";
|
||||
autoStart = true;
|
||||
dependsOn = ["gluetun"];
|
||||
ports = [
|
||||
"8080:8080"
|
||||
"58846:58846"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=container:gluetun"
|
||||
];
|
||||
volumes = [
|
||||
"/var/lib/qbittorrent:/config:rw"
|
||||
"/mnt/data/media/downloads:/downloads:rw"
|
||||
];
|
||||
environmentFiles = [
|
||||
config.age.secrets.gluetunEnvironment.path
|
||||
];
|
||||
environment = {
|
||||
PUID = "994";
|
||||
PGID = "993";
|
||||
TZ = "Europe/Stockholm";
|
||||
WEBUI_PORT = "${builtins.toString cfg.qbittorrent.port}";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.slskd.enable {
|
||||
slskd = {
|
||||
image = "slskd/slskd:latest";
|
||||
autoStart = true;
|
||||
dependsOn = ["gluetun"];
|
||||
ports = [
|
||||
"5030:5030"
|
||||
"5031:5031"
|
||||
"50300:50300"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=container:gluetun"
|
||||
];
|
||||
volumes = [
|
||||
"/var/lib/slskd:/app:rw"
|
||||
"/mnt/data/media/downloads:/downloads:rw"
|
||||
];
|
||||
environmentFiles = [
|
||||
config.age.secrets.gluetunEnvironment.path
|
||||
config.age.secrets.slskd.path
|
||||
];
|
||||
environment = {
|
||||
TZ = "Europe/Stockholm";
|
||||
PUID = "981";
|
||||
PGID = "982";
|
||||
SLSKD_REMOTE_CONFIGURATION = "true";
|
||||
SLSKD_REMOTE_FILE_MANAGEMENT = "true";
|
||||
SLSKD_DOWNLOADS_DIR = "/downloads";
|
||||
SLSKD_UMASK = "022";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.pihole.enable {
|
||||
pihole = {
|
||||
autoStart = true;
|
||||
image = "pihole/pihole:2025.08.0";
|
||||
volumes = [
|
||||
"/var/lib/pihole:/etc/pihole/"
|
||||
"/var/lib/dnsmasq.d:/etc/dnsmasq.d/"
|
||||
];
|
||||
environment = {
|
||||
TZ = "Europe/Stockholm";
|
||||
CUSTOM_CACHE_SIZE = "0";
|
||||
WEBTHEME = "default-darker";
|
||||
};
|
||||
environmentFiles = getPiholeSecret config.networking.hostName;
|
||||
ports = [
|
||||
"53:53/tcp"
|
||||
"53:53/udp"
|
||||
"8053:80/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--cap-add=NET_ADMIN"
|
||||
"--cap-add=SYS_NICE"
|
||||
"--cap-add=SYS_TIME"
|
||||
];
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "prowlarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.${unit};
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${unit}.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Prowlarr";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "PVR indexer";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "prowlarr.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Arr";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
${unit} = {
|
||||
enable = true;
|
||||
};
|
||||
flaresolverr = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services = {
|
||||
prowlarr = {
|
||||
loadBalancer.servers = [{url = "http://127.0.0.1:9696";}];
|
||||
};
|
||||
flaresolverr = {
|
||||
loadBalancer.servers = [{url = "http://127.0.0.1:8191";}];
|
||||
};
|
||||
};
|
||||
routers = {
|
||||
prowlarr = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "prowlarr";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
flaresolverr = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`flaresolverr.${srv.domain}`)";
|
||||
service = "flaresolverr";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "radarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.${unit};
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${unit}.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Radarr";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Film collection manager";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "radarr.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Arr";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
services.traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.radarr.loadBalancer.servers = [{url = "http://127.0.0.1:7878";}];
|
||||
routers = {
|
||||
radarr = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "radarr";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
17
modules/server/services/bazarr/default.nix
Normal file
17
modules/server/services/bazarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "bazarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
};
|
||||
}
|
||||
19
modules/server/services/default.nix
Normal file
19
modules/server/services/default.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
imports = [
|
||||
./bazarr
|
||||
./flaresolverr
|
||||
./gitea
|
||||
./homepage-dashboard
|
||||
./jellyfin
|
||||
./jellyseerr
|
||||
./lidarr
|
||||
./n8n
|
||||
./nextcloud
|
||||
./ollama
|
||||
./prowlarr
|
||||
./radarr
|
||||
./sonarr
|
||||
./uptime-kuma
|
||||
./vaultwarden
|
||||
];
|
||||
}
|
||||
16
modules/server/services/flaresolverr/default.nix
Normal file
16
modules/server/services/flaresolverr/default.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "flaresolverr";
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
${unit} = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
94
modules/server/services/gitea/default.nix
Normal file
94
modules/server/services/gitea/default.nix
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
unit = "gitea";
|
||||
cfg = config.server.services.${unit};
|
||||
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets.giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age";
|
||||
|
||||
server.infra = {
|
||||
fail2ban.jails.${unit} = {
|
||||
serviceName = "${unit}";
|
||||
failRegex = ''.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>'';
|
||||
};
|
||||
|
||||
postgresql.databases = [
|
||||
{database = "gitea";}
|
||||
];
|
||||
};
|
||||
|
||||
services = {
|
||||
cloudflared = {
|
||||
enable = true;
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${domain}".service = "http://localhost:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
gitea = {
|
||||
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 = domain;
|
||||
};
|
||||
|
||||
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 = domain;
|
||||
LANDING_PAGE = "explore";
|
||||
HTTP_PORT = cfg.port;
|
||||
ROOT_URL = "https://${domain}/";
|
||||
};
|
||||
|
||||
security.DISABLE_GIT_HOOKS = false;
|
||||
service.DISABLE_REGISTRATION = true;
|
||||
session.COOKIE_SECURE = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
227
modules/server/services/homepage-dashboard/default.nix
Normal file
227
modules/server/services/homepage-dashboard/default.nix
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
self,
|
||||
clib,
|
||||
...
|
||||
}: let
|
||||
unit = "homepage-dashboard";
|
||||
cfg = config.server.services.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
homepageEnvironment = {
|
||||
file = "${self}/secrets/homepageEnvironment.age";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
glances.enable = true;
|
||||
|
||||
${unit} = {
|
||||
enable = true;
|
||||
environmentFile = config.age.secrets.homepageEnvironment.path;
|
||||
|
||||
settings = {
|
||||
color = "stone";
|
||||
theme = "dark";
|
||||
headerStyle = "clean";
|
||||
statusStyle = "dot";
|
||||
hideVersion = true;
|
||||
useEqualHeights = true;
|
||||
|
||||
layout = [
|
||||
{
|
||||
Glances = {
|
||||
header = false;
|
||||
style = "row";
|
||||
columns = 4;
|
||||
};
|
||||
}
|
||||
{
|
||||
Arr = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
{
|
||||
Downloads = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
{
|
||||
Media = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
{
|
||||
Services = {
|
||||
header = true;
|
||||
style = "column";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
widgets = [
|
||||
{
|
||||
openmeteo = {
|
||||
label = "Kalmar";
|
||||
timezone = "Europe/Stockholm";
|
||||
units = "metric";
|
||||
cache = 5;
|
||||
latitude = 56.707262;
|
||||
longitude = 16.324541;
|
||||
};
|
||||
}
|
||||
{
|
||||
resources = {
|
||||
label = "SYSTEM";
|
||||
memory = true;
|
||||
cpu = true;
|
||||
uptime = false;
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
services = let
|
||||
homepageCategories = [
|
||||
"Arr"
|
||||
"Media"
|
||||
"Downloads"
|
||||
"Services"
|
||||
];
|
||||
allServices = srv.services;
|
||||
|
||||
getDomain = s: clib.server.mkHostDomain config s;
|
||||
|
||||
homepageServicesFor = category:
|
||||
lib.filterAttrs
|
||||
(
|
||||
name: value:
|
||||
name
|
||||
!= unit
|
||||
&& value ? homepage
|
||||
&& value.homepage.category == category
|
||||
)
|
||||
allServices;
|
||||
in
|
||||
lib.lists.forEach homepageCategories (cat: {
|
||||
"${cat}" =
|
||||
lib.lists.forEach
|
||||
(lib.attrsets.mapAttrsToList (name: _value: name) (homepageServicesFor cat))
|
||||
(x: let
|
||||
service = allServices.${x};
|
||||
domain = getDomain service;
|
||||
in {
|
||||
"${service.homepage.name}" = {
|
||||
icon = service.homepage.icon;
|
||||
description = service.homepage.description;
|
||||
href = "https://${service.subdomain}.${domain}${service.homepage.path or ""}";
|
||||
siteMonitor = "https://${service.subdomain}.${domain}${x.homepage.path or ""}";
|
||||
};
|
||||
});
|
||||
})
|
||||
++ [
|
||||
{
|
||||
Glances = let
|
||||
glancesShared = {
|
||||
type = "glances";
|
||||
url = "http://localhost:${toString config.services.glances.port}";
|
||||
chart = true;
|
||||
version = 4;
|
||||
};
|
||||
in [
|
||||
{
|
||||
Memory = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "memory";
|
||||
refreshInterval = 2000;
|
||||
pointsLimit = 30;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"CPU Usage" = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "cpu";
|
||||
refreshInterval = 2000;
|
||||
pointsLimit = 30;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
"CPU Temp" = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "sensor:Tctl";
|
||||
refreshInterval = 5000;
|
||||
pointsLimit = 20;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"GPU Radeon" = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "sensor:junction";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"GPU Intel" = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "sensor:pkg";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"ZFS Pool" = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "fs:/mnt/data";
|
||||
refreshInterval = 30000;
|
||||
pointsLimit = 20;
|
||||
diskUnits = "bytes";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
Processes = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "process";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
Network = {
|
||||
widget =
|
||||
glancesShared
|
||||
// {
|
||||
metric = "network:enp6s0";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
21
modules/server/services/jellyfin/default.nix
Normal file
21
modules/server/services/jellyfin/default.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
unit = "jellyfin";
|
||||
cfg = config.server.services.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
jellyfin-ffmpeg
|
||||
];
|
||||
};
|
||||
}
|
||||
15
modules/server/services/jellyseerr/default.nix
Normal file
15
modules/server/services/jellyseerr/default.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "jellyseerr";
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
port = cfg.port;
|
||||
};
|
||||
};
|
||||
}
|
||||
17
modules/server/services/lidarr/default.nix
Normal file
17
modules/server/services/lidarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "lidarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
};
|
||||
}
|
||||
17
modules/server/services/n8n/default.nix
Normal file
17
modules/server/services/n8n/default.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "n8n";
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
n8n = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
101
modules/server/services/nextcloud/default.nix
Normal file
101
modules/server/services/nextcloud/default.nix
Normal file
@@ -0,0 +1,101 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
unit = "nextcloud";
|
||||
cfg = config.server.services.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age";
|
||||
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
|
||||
};
|
||||
|
||||
server.infra.fail2ban.jails.nextcloud = {
|
||||
serviceName = "${unit}";
|
||||
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
||||
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)?"'';
|
||||
};
|
||||
|
||||
services = {
|
||||
${unit} = {
|
||||
enable = true;
|
||||
package = pkgs.nextcloud32;
|
||||
hostName = "nextcloud";
|
||||
configureRedis = true;
|
||||
caching = {
|
||||
redis = true;
|
||||
};
|
||||
phpOptions = {
|
||||
"opcache.interned_strings_buffer" = "32";
|
||||
};
|
||||
maxUploadSize = "50G";
|
||||
settings = {
|
||||
maintenance_window_start = "1";
|
||||
trusted_proxies = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
trusted_domains = ["cloud.${srv.domain}"];
|
||||
overwriteprotocol = "https";
|
||||
enabledPreviewProviders = [
|
||||
"OC\\Preview\\BMP"
|
||||
"OC\\Preview\\GIF"
|
||||
"OC\\Preview\\JPEG"
|
||||
"OC\\Preview\\Krita"
|
||||
"OC\\Preview\\MarkDown"
|
||||
"OC\\Preview\\MP3"
|
||||
"OC\\Preview\\OpenDocument"
|
||||
"OC\\Preview\\PNG"
|
||||
"OC\\Preview\\TXT"
|
||||
"OC\\Preview\\XBitmap"
|
||||
"OC\\Preview\\HEIC"
|
||||
];
|
||||
};
|
||||
config = {
|
||||
dbtype = "pgsql";
|
||||
dbuser = "nextcloud";
|
||||
dbhost = "/run/postgresql";
|
||||
dbname = "nextcloud";
|
||||
adminuser = "cnst";
|
||||
adminpassFile = config.age.secrets.nextcloudAdminPass.path;
|
||||
};
|
||||
};
|
||||
|
||||
nginx = {
|
||||
defaultListen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 8182;
|
||||
}
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 8482;
|
||||
}
|
||||
];
|
||||
virtualHosts.nextcloud = {
|
||||
forceSSL = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
server.infra.postgresql.databases = [
|
||||
{
|
||||
database = "nextcloud";
|
||||
}
|
||||
];
|
||||
systemd.services."nextcloud-setup" = {
|
||||
requires = ["postgresql.service"];
|
||||
after = ["postgresql.service"];
|
||||
};
|
||||
};
|
||||
}
|
||||
28
modules/server/services/ollama/default.nix
Normal file
28
modules/server/services/ollama/default.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
unit = "ollama";
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
ollama
|
||||
intel-compute-runtime
|
||||
intel-graphics-compiler
|
||||
level-zero
|
||||
];
|
||||
services.open-webui = {
|
||||
enable = true;
|
||||
host = "0.0.0.0";
|
||||
port = 8001;
|
||||
environment = {
|
||||
ANONYMIZED_TELEMETRY = "False";
|
||||
BYPASS_MODEL_ACCESS_CONTROL = "True";
|
||||
OLLAMA_BASE_URL = "http://localhost:11434";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
16
modules/server/services/prowlarr/default.nix
Normal file
16
modules/server/services/prowlarr/default.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "prowlarr";
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
${unit} = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
17
modules/server/services/radarr/default.nix
Normal file
17
modules/server/services/radarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "radarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
};
|
||||
}
|
||||
17
modules/server/services/sonarr/default.nix
Normal file
17
modules/server/services/sonarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "sonarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
};
|
||||
}
|
||||
16
modules/server/services/uptime-kuma/default.nix
Normal file
16
modules/server/services/uptime-kuma/default.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "uptime-kuma";
|
||||
cfg = config.server.services.${unit};
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
${unit} = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
59
modules/server/services/vaultwarden/default.nix
Normal file
59
modules/server/services/vaultwarden/default.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
# from @fufexan & @notthebee
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
unit = "vaultwarden";
|
||||
cfg = config.server.services.${unit};
|
||||
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";
|
||||
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
||||
};
|
||||
|
||||
server.infra.fail2ban.jails.${unit} = {
|
||||
serviceName = "${unit}";
|
||||
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'';
|
||||
};
|
||||
|
||||
services = {
|
||||
cloudflared = {
|
||||
enable = true;
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${domain}".service = "http://localhost:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
vaultwarden = {
|
||||
enable = true;
|
||||
environmentFile = config.age.secrets.vaultwardenEnvironment.path;
|
||||
|
||||
backupDir = "/var/backup/vaultwarden";
|
||||
|
||||
config = {
|
||||
DOMAIN = "https://${domain}";
|
||||
SIGNUPS_ALLOWED = false;
|
||||
ROCKET_ADDRESS = "127.0.0.1";
|
||||
ROCKET_PORT = cfg.port;
|
||||
IP_HEADER = "CF-Connecting-IP";
|
||||
|
||||
logLevel = "warn";
|
||||
extendedLogging = true;
|
||||
useSyslog = true;
|
||||
invitationsAllowed = true;
|
||||
showPasswordHint = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd.services.backup-vaultwarden.serviceConfig = {
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "sonarr";
|
||||
srv = config.server;
|
||||
cfg = config.server.${unit};
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${unit}.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Sonarr";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Series collection manager";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "sonarr.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Arr";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
user = srv.user;
|
||||
group = srv.group;
|
||||
};
|
||||
services.traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.sonarr.loadBalancer.servers = [{url = "http://127.0.0.1:8989";}];
|
||||
routers = {
|
||||
sonarr = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "sonarr";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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"];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "uptime-kuma";
|
||||
cfg = config.server.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/uptime-kuma";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "uptime.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Uptime Kuma";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Service monitoring tool";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "uptime-kuma.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
${unit} = {
|
||||
enable = true;
|
||||
};
|
||||
traefik = {
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
services.uptime-kuma.loadBalancer.servers = [{url = "http://127.0.0.1:3001";}];
|
||||
routers = {
|
||||
uptime-kuma = {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${cfg.url}`)";
|
||||
service = "uptime-kuma";
|
||||
tls.certResolver = "letsencrypt";
|
||||
# middlewares = ["authentik"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
# from @fufexan & @notthebee
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkEnableOption;
|
||||
vcfg = config.services.vaultwarden.config;
|
||||
cfg = config.server.vaultwarden;
|
||||
in {
|
||||
options = {
|
||||
server.vaultwarden = {
|
||||
enable = mkEnableOption "Enables vaultwarden";
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${cfg.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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";
|
||||
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
||||
};
|
||||
|
||||
server = {
|
||||
fail2ban = lib.mkIf config.server.fail2ban.enable {
|
||||
jails = {
|
||||
vaultwarden = {
|
||||
serviceName = "vaultwarden";
|
||||
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.backup-vaultwarden.serviceConfig = {
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
|
||||
services = {
|
||||
vaultwarden = {
|
||||
enable = true;
|
||||
environmentFile = config.age.secrets.vaultwardenEnvironment.path;
|
||||
|
||||
backupDir = "/var/backup/vaultwarden";
|
||||
|
||||
config = {
|
||||
DOMAIN = "https://${cfg.url}";
|
||||
SIGNUPS_ALLOWED = false;
|
||||
ROCKET_ADDRESS = "127.0.0.1";
|
||||
ROCKET_PORT = 8222;
|
||||
IP_HEADER = "CF-Connecting-IP";
|
||||
|
||||
logLevel = "warn";
|
||||
extendedLogging = true;
|
||||
useSyslog = true;
|
||||
invitationsAllowed = true;
|
||||
showPasswordHint = false;
|
||||
};
|
||||
};
|
||||
cloudflared = {
|
||||
enable = true;
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${cfg.url}".service = "http://${vcfg.ROCKET_ADDRESS}:${toString vcfg.ROCKET_PORT}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,8 +2,7 @@
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
}: let
|
||||
inherit (lib) mkOption types;
|
||||
|
||||
sshKeys = {
|
||||
@@ -16,14 +15,14 @@ let
|
||||
keyName = config.settings.accounts.sshUser or null;
|
||||
|
||||
selectedKey =
|
||||
if keyName != null then
|
||||
if keyName != null
|
||||
then
|
||||
lib.attrByPath [
|
||||
keyName
|
||||
] (builtins.abort "No SSH key defined for hostname/key '${toString keyName}'") sshKeys
|
||||
else
|
||||
builtins.abort "No accounts.sshUser provided, cannot select SSH key.";
|
||||
in
|
||||
{
|
||||
] (builtins.abort "No SSH key defined for hostname/key '${toString keyName}'")
|
||||
sshKeys
|
||||
else builtins.abort "No accounts.sshUser provided, cannot select SSH key.";
|
||||
in {
|
||||
options.settings.accounts = {
|
||||
username = mkOption {
|
||||
type = types.str;
|
||||
@@ -46,5 +45,21 @@ in
|
||||
default = null;
|
||||
description = "Optional override for selecting an SSH key by name";
|
||||
};
|
||||
domains = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
local = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "The local domain of the host";
|
||||
};
|
||||
public = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "example.com";
|
||||
description = "The public domain of the host";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ in
|
||||
example = 1080;
|
||||
};
|
||||
refreshRate = mkOption {
|
||||
type = types.int;
|
||||
default = 60;
|
||||
type = types.str;
|
||||
default = "60";
|
||||
};
|
||||
transform = mkOption {
|
||||
type = types.int;
|
||||
|
||||
@@ -4,5 +4,8 @@
|
||||
allowUnfree = true;
|
||||
input-fonts.acceptLicense = true;
|
||||
};
|
||||
|
||||
overlays = [
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
"aarch64-linux"
|
||||
];
|
||||
|
||||
perSystem =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
perSystem = {pkgs, ...}: {
|
||||
packages = {
|
||||
# instant repl with automatic flake loading
|
||||
repl = pkgs.callPackage ./repl {};
|
||||
|
||||
11
secrets/crowdsecApi.age
Normal file
11
secrets/crowdsecApi.age
Normal file
@@ -0,0 +1,11 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 t9iOEg lf7aPbZX2v3WGzE/KI/069DBObphqrDtjq7rhNriGl8
|
||||
Vv+Pqk6DbcE5R1A9135gVKroCex1xKsCLPETZdT3yTg
|
||||
-> ssh-ed25519 KUYMFA XxtBSmCwrQCZ9G3VcCrbzTdMshTK1pjlHPYj7fke818
|
||||
9tO2EcnHPD6v3TNeuZdL+zP39SM5R5q7om5sCFDB8lg
|
||||
-> ssh-ed25519 76RhUQ I6O/fYFRqYxExC9uLijZr6/kFze7uze0cIudCsl2jTo
|
||||
WAwb822vVj5UtUAdE1oVJ0/q6nQbWqdx0OHuGEogO7M
|
||||
-> ssh-ed25519 Jf8sqw gWBoe4HhXNw7Ih58lQ/L2vBoQfbU1ht8+ZSLUx/4TWk
|
||||
xor0ieJ2UI5bK4rSlCM0dX61PVbxYE37FNry0YSmHG4
|
||||
--- Cp8b3eTb3NfjPFvBE12a2c+Yni2jW6DZUK10IaXmmvo
|
||||
w<EFBFBD>xq<EFBFBD><EFBFBD>z:<3A>.{<7B>?<3F><><EFBFBD>f<EFBFBD><66><1D><><16><>A<EFBFBD>jT<6A><54>{<7B>J <20><>
|
||||
Binary file not shown.
11
secrets/mikrotikSecret.age
Normal file
11
secrets/mikrotikSecret.age
Normal file
@@ -0,0 +1,11 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 t9iOEg MLi7IOM8QlpvlCMSmo4SwZbTwZ9pyysSbiMMuWD/dyU
|
||||
cotV5TJf7oyyXIaAmu8n9Ie1rl27i8w7hsduwtQFnis
|
||||
-> ssh-ed25519 KUYMFA BhFQ/RXOH8L7gl/FSabAUv28fbaod+muvTGSV3rYQSs
|
||||
fWqwAkhSAmg6YB+yEtj0e83Q4XO/r+TBnMTN7vXBNqU
|
||||
-> ssh-ed25519 76RhUQ b1fDfGPNdJ9c3wtr8ww0mW5K4fKJxpxxTZy/ZCECWzs
|
||||
qhbvucUrv7dzOPKUmUaRs/AtXtwQfy/qp5HnaYzZ5eQ
|
||||
-> ssh-ed25519 Jf8sqw 19D2ztjyxJfGQAiUOTdgWyC0ZFso/wrC9VPEkmI34U8
|
||||
PavT5O8M6Zc2Num9Hb2sY+F3UmMPqRgjUZxuvP6AhyM
|
||||
--- uYOcbsL7JWoDF2mRUDLhXrbp6ssLFbQ9+a6RhAXNNPA
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> X<><58>PC<50><43>h<EFBFBD>;
|
||||
@@ -63,6 +63,8 @@ in {
|
||||
"wwwCloudflared.age".publicKeys = kima ++ sobotka;
|
||||
"authentikCloudflared.age".publicKeys = kima ++ sobotka;
|
||||
"sobotkaTsAuth.age".publicKeys = kima ++ sobotka;
|
||||
"mikrotikSecret.age".publicKeys = kima ++ sobotka;
|
||||
"crowdsecApi.age".publicKeys = kima ++ sobotka;
|
||||
|
||||
# Ziggy-specific
|
||||
"cloudflareDnsCredentialsZiggy.age".publicKeys = kima ++ ziggy;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
enable = true;
|
||||
};
|
||||
ghostty = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
};
|
||||
helix = {
|
||||
enable = true;
|
||||
@@ -57,7 +57,7 @@
|
||||
enable = false;
|
||||
};
|
||||
nvf = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
};
|
||||
nwg-bar = {
|
||||
enable = true;
|
||||
|
||||
Reference in New Issue
Block a user