1 Commits

Author SHA1 Message Date
d53bf7546a broken 2 2025-10-05 10:02:39 +02:00
88 changed files with 2153 additions and 2194 deletions

370
flake.lock generated
View File

@@ -8,11 +8,11 @@
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1760836749, "lastModified": 1754433428,
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=",
"owner": "ryantm", "owner": "ryantm",
"repo": "agenix", "repo": "agenix",
"rev": "2f0f812f69f3eb4140157fe15e12739adf82e32a", "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -29,11 +29,11 @@
"systems": "systems_2" "systems": "systems_2"
}, },
"locked": { "locked": {
"lastModified": 1761238850, "lastModified": 1758874004,
"narHash": "sha256-WGoqR+ULsh1w7yDNAtJiE27HX6zSlGPR4I2pgjAU/SA=", "narHash": "sha256-+RUCBtT01Z595NpGc6Tvms+dJ/C/cn1zdjT9+gE6dbU=",
"owner": "anyrun-org", "owner": "anyrun-org",
"repo": "anyrun", "repo": "anyrun",
"rev": "ae3c499316e9aa568acb3832566a1978ca665748", "rev": "3c571bc1514c4211d1d6c011a1d482f97efd9c5f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -83,11 +83,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760101617, "lastModified": 1759499898,
"narHash": "sha256-8jf/3ZCi+B7zYpIyV04+3wm72BD7Z801IlOzsOACR7I=", "narHash": "sha256-UNzYHLWfkSzLHDep5Ckb5tXc0fdxwPIrT+MY4kpQttM=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "aquamarine", "repo": "aquamarine",
"rev": "1826a9923881320306231b1c2090379ebf9fa4f8", "rev": "655e067f96fd44b3f5685e17f566b0e4d535d798",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -100,26 +100,29 @@
"inputs": { "inputs": {
"authentik-src": "authentik-src", "authentik-src": "authentik-src",
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"flake-parts": "flake-parts_2", "flake-parts": [
"flake-parts"
],
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"napalm": "napalm", "napalm": "napalm",
"nixpkgs": "nixpkgs_3", "nixpkgs": [
"nixpkgs"
],
"pyproject-build-systems": "pyproject-build-systems", "pyproject-build-systems": "pyproject-build-systems",
"pyproject-nix": "pyproject-nix", "pyproject-nix": "pyproject-nix",
"systems": "systems_3", "systems": "systems_3",
"uv2nix": "uv2nix" "uv2nix": "uv2nix"
}, },
"locked": { "locked": {
"lastModified": 1758177015, "lastModified": 1759322529,
"narHash": "sha256-PCUWdbaxayY3YfSjVlyddBMYoGvSaRysd5AmZ8gqSFs=", "narHash": "sha256-yiv/g/tiJI3PI95F7vhTnaf1TDsIkFLrmmFTjWfb6pQ=",
"owner": "nix-community", "owner": "nix-community",
"repo": "authentik-nix", "repo": "authentik-nix",
"rev": "4c626ed84cc0f1278bfba0f534efd6cba2788d75", "rev": "69fac057b2e553ee17c9a09b822d735823d65a6c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "version/2025.8.3",
"repo": "authentik-nix", "repo": "authentik-nix",
"type": "github" "type": "github"
} }
@@ -127,16 +130,16 @@
"authentik-src": { "authentik-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1758035356, "lastModified": 1759190535,
"narHash": "sha256-DkvxDwHCfSqEpZ9rRXNR8MP0Mz/y1kHAr38exrHQ39c=", "narHash": "sha256-pIzDaoDWc58cY/XhsyweCwc4dfRvkaT/zqsV1gDSnCI=",
"owner": "goauthentik", "owner": "goauthentik",
"repo": "authentik", "repo": "authentik",
"rev": "680feaefa17934471a6b33ebc35caf5b64120404", "rev": "8d3a289d12c7de2f244c76493af7880f70d08af2",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "goauthentik", "owner": "goauthentik",
"ref": "version/2025.8.3", "ref": "version/2025.8.4",
"repo": "authentik", "repo": "authentik",
"type": "github" "type": "github"
} }
@@ -146,15 +149,15 @@
"flake-schemas": "flake-schemas", "flake-schemas": "flake-schemas",
"home-manager": "home-manager_2", "home-manager": "home-manager_2",
"jovian": "jovian", "jovian": "jovian",
"nixpkgs": "nixpkgs_4", "nixpkgs": "nixpkgs_3",
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1761326352, "lastModified": 1759532138,
"narHash": "sha256-DoR4mHaStX6Dg2Gilc2Dqr/XaxXmQTOQS5cZ5xKPQJY=", "narHash": "sha256-sLQIlgDwMP3mEY2PwjGW+cL56QQ2n2WXoZ3GpG5QWOY=",
"owner": "chaotic-cx", "owner": "chaotic-cx",
"repo": "nyx", "repo": "nyx",
"rev": "6492dc810f2f250ef95096910a44f03eea6a594f", "rev": "bad02bbca5b5c6d45539a0d740ad0e21b1ba9afc",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -209,11 +212,11 @@
"rust-analyzer-src": "rust-analyzer-src" "rust-analyzer-src": "rust-analyzer-src"
}, },
"locked": { "locked": {
"lastModified": 1761374215, "lastModified": 1759646430,
"narHash": "sha256-YmnUYXjacFHa8fWCo8gBAHpqlcG8+P5+5YYFhy6hOkg=", "narHash": "sha256-V8mjmGzi9nS7BZfhpzYAOUg3BcCsC6MrEh9xlKq3+7s=",
"owner": "nix-community", "owner": "nix-community",
"repo": "fenix", "repo": "fenix",
"rev": "b0fa429fc946e6e716dff3bfb97ce6383eae9359", "rev": "b326bea4d58c9a58b346f17c710538eac00f71d1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -324,14 +327,16 @@
}, },
"flake-parts_2": { "flake-parts_2": {
"inputs": { "inputs": {
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": [
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1756770412, "lastModified": 1759362264,
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=", "narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "4524271976b625a4a605beefd893f270620fd751", "rev": "758cf7296bee11f1706a574c77d072b8a7baa881",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -342,27 +347,7 @@
}, },
"flake-parts_3": { "flake-parts_3": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": "nixpkgs-lib"
"nixpkgs"
]
},
"locked": {
"lastModified": 1760948891,
"narHash": "sha256-TmWcdiUUaWk8J4lpjzu4gCGxWY6/Ok7mOK4fIFfBuU4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "864599284fc7c0ba6357ed89ed5e2cd5040f0c04",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_4": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_2"
}, },
"locked": { "locked": {
"lastModified": 1753121425, "lastModified": 1753121425,
@@ -378,7 +363,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_5": { "flake-parts_4": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
"lanzaboote", "lanzaboote",
@@ -399,7 +384,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_6": { "flake-parts_5": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
"nvf", "nvf",
@@ -420,7 +405,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_7": { "flake-parts_6": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
"tuirun", "tuirun",
@@ -478,8 +463,8 @@
}, },
"fonts": { "fonts": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_4", "flake-parts": "flake-parts_3",
"nixpkgs": "nixpkgs_5" "nixpkgs": "nixpkgs_4"
}, },
"locked": { "locked": {
"lastModified": 1753431871, "lastModified": 1753431871,
@@ -506,11 +491,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760663237, "lastModified": 1759523803,
"narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=", "narHash": "sha256-PTod9NG+i3XbbnBKMl/e5uHDBYpwIWivQ3gOWSEuIEM=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37", "rev": "cfc9f7bb163ad8542029d303e599c0f7eee09835",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -586,11 +571,11 @@
}, },
"hardware": { "hardware": {
"locked": { "locked": {
"lastModified": 1760958188, "lastModified": 1759582739,
"narHash": "sha256-2m1S4jl+GEDtlt2QqeHil8Ny456dcGSKJAM7q3j/BFU=", "narHash": "sha256-spZegilADH0q5OngM86u6NmXxduCNv5eX9vCiUPhOYc=",
"owner": "nixos", "owner": "nixos",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "d6645c340ef7d821602fd2cd199e8d1eed10afbc", "rev": "3441b5242af7577230a78ffb03542add264179ab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -601,15 +586,15 @@
}, },
"helix-flake": { "helix-flake": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_6", "nixpkgs": "nixpkgs_5",
"rust-overlay": "rust-overlay_2" "rust-overlay": "rust-overlay_2"
}, },
"locked": { "locked": {
"lastModified": 1761141169, "lastModified": 1759605748,
"narHash": "sha256-5IZjbTvP5dNTD8CbEYlNbicdGcbCN9SC9ksMm2ZEXH0=", "narHash": "sha256-qALSaIE4fbTo0wbPjEp7RZKbtFk1cDhRZ0BYOHW0JwQ=",
"owner": "helix-editor", "owner": "helix-editor",
"repo": "helix", "repo": "helix",
"rev": "d79cce4e4bfc24dd204f1b294c899ed73f7e9453", "rev": "6fffaf6a7ded9a12fb2d5715a4eb83787a5e6402",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -625,11 +610,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761344779, "lastModified": 1759573136,
"narHash": "sha256-6LNSptFYhiAd0M/maJoixJw7V0Kp5BSoMRtIahcfu3M=", "narHash": "sha256-ILSPD0Dm8p0w0fCVzOx98ZH8yFDrR75GmwmH3fS2VnE=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "c644cb018f9fdec55f5ac2afb4713a8c7beb757c", "rev": "5f06ceafc6c9b773a776b9195c3f47bbe1defa43",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -667,11 +652,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761266473, "lastModified": 1759337100,
"narHash": "sha256-QxCyKWBmuzI+eMhYV1JmbZsiUnBNATRP1EW34OBt5Vg=", "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "5c71d4a730bd3c972befff343bb074421e345937", "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -725,11 +710,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760445448, "lastModified": 1759490292,
"narHash": "sha256-fXGjL6dw31FPFRrmIemzGiNSlfvEJTJNsmadZi+qNhI=", "narHash": "sha256-T6iWzDOXp8Wv0KQOCTHpBcmAOdHJ6zc/l9xaztW6Ivc=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprgraphics", "repo": "hyprgraphics",
"rev": "50fb9f069219f338a11cf0bcccb9e58357d67757", "rev": "9431db625cd9bb66ac55525479dce694101d6d7a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -754,11 +739,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759490292, "lastModified": 1750621377,
"narHash": "sha256-T6iWzDOXp8Wv0KQOCTHpBcmAOdHJ6zc/l9xaztW6Ivc=", "narHash": "sha256-8u6b5oAdX0rCuoR8wFenajBRmI+mzbpNig6hSCuWUzE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprgraphics", "repo": "hyprgraphics",
"rev": "9431db625cd9bb66ac55525479dce694101d6d7a", "rev": "b3d628d01693fb9bb0a6690cd4e7b80abda04310",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -812,17 +797,17 @@
"hyprlang": "hyprlang", "hyprlang": "hyprlang",
"hyprutils": "hyprutils", "hyprutils": "hyprutils",
"hyprwayland-scanner": "hyprwayland-scanner_2", "hyprwayland-scanner": "hyprwayland-scanner_2",
"nixpkgs": "nixpkgs_7", "nixpkgs": "nixpkgs_6",
"pre-commit-hooks": "pre-commit-hooks", "pre-commit-hooks": "pre-commit-hooks",
"systems": "systems_4", "systems": "systems_4",
"xdph": "xdph" "xdph": "xdph"
}, },
"locked": { "locked": {
"lastModified": 1761389866, "lastModified": 1759530922,
"narHash": "sha256-RupwqaJ3JF5dF9iuJX+y0EZslmIuRs7+n+wnngtBqak=", "narHash": "sha256-9NgZKpibALekGTPDc2O8lP8vFealQSZkXe+L+S7MMZU=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland", "repo": "hyprland",
"rev": "b10b9660004b3dfaf9e11a305d78f24955b089a4", "rev": "76d998743ac10e712238c1016db4d8e8d16f1049",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -889,11 +874,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759610243, "lastModified": 1749046714,
"narHash": "sha256-+KEVnKBe8wz+a6dTLq8YDcF3UrhQElwsYJaVaHXJtoI=", "narHash": "sha256-kymV5FMnddYGI+UjwIw8ceDjdeg7ToDVjbHCvUlhn14=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-protocols", "repo": "hyprland-protocols",
"rev": "bd153e76f751f150a09328dbdeb5e4fab9d23622", "rev": "613878cb6f459c5e323aaafe1e6f388ac8a36330",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1021,11 +1006,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760023949, "lastModified": 1759572448,
"narHash": "sha256-fu0B4duamVdbkPio/czu1XhsPLRXUJpZLDrSk3nih4U=", "narHash": "sha256-o+r44fqPQM+/hQdjFy9qV9C51Jhty6M4icFVYocyJfA=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlock", "repo": "hyprlock",
"rev": "36ec73f166d9434a3f27c96c575198906f77644a", "rev": "c8a6768dca626cf7d7cbc333095f048bc007b6d9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1059,11 +1044,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760120448, "lastModified": 1754481642,
"narHash": "sha256-l/OxM4q/nLVv47OuS4bG2J7k0m+G7/3AMtvrV64XLb0=", "narHash": "sha256-e1phd6KwtUsS9C2ShD+fQvfk2Dgr2JQi+rTDQUW15iE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprpaper", "repo": "hyprpaper",
"rev": "1733e0025b194c9bc083f4cd8782c5f151858a58", "rev": "bcb1ffa322369c4898347ab5a7399a3d18494c8f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1084,11 +1069,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759619523, "lastModified": 1759490926,
"narHash": "sha256-r1ed7AR2ZEb2U8gy321/Xcp1ho2tzn+gG1te/Wxsj1A=", "narHash": "sha256-7IbZGJ5qAAfZsGhBHIsP8MBsfuFYS0hsxYHVkkeDG5Q=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprutils", "repo": "hyprutils",
"rev": "3df7bde01efb3a3e8e678d1155f2aa3f19e177ef", "rev": "94cce794344538c4d865e38682684ec2bbdb2ef3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1159,11 +1144,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1755184602, "lastModified": 1750371869,
"narHash": "sha256-RCBQN8xuADB0LEgaKbfRqwm6CdyopE1xIEhNc67FAbw=", "narHash": "sha256-lGk4gLjgZQ/rndUkzmPYcgbHr8gKU5u71vyrjnwfpB4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprwayland-scanner", "repo": "hyprwayland-scanner",
"rev": "b3b0f1f40ae09d4447c20608e5a4faf8bf3c492d", "rev": "aa38edd6e3e277ae6a97ea83a69261a5c3aab9fd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1206,11 +1191,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761202163, "lastModified": 1759387127,
"narHash": "sha256-6RySf5VQElrm7RYGWxlIkNttemDp4FF0aH+LX435G2Y=", "narHash": "sha256-uuwJAP92SkHmnI1zo7rrK/gEuHtb97vFZcMa5w+0SZA=",
"owner": "Jovian-Experiments", "owner": "Jovian-Experiments",
"repo": "Jovian-NixOS", "repo": "Jovian-NixOS",
"rev": "47976126007d9658ca4ac4dd933bea8846170fd9", "rev": "0cc290e05882745060fccfe6d7d073f913e0cce7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1223,8 +1208,8 @@
"inputs": { "inputs": {
"crane": "crane", "crane": "crane",
"flake-compat": "flake-compat_4", "flake-compat": "flake-compat_4",
"flake-parts": "flake-parts_5", "flake-parts": "flake-parts_4",
"nixpkgs": "nixpkgs_8", "nixpkgs": "nixpkgs_7",
"pre-commit-hooks-nix": "pre-commit-hooks-nix", "pre-commit-hooks-nix": "pre-commit-hooks-nix",
"rust-overlay": "rust-overlay_3" "rust-overlay": "rust-overlay_3"
}, },
@@ -1293,11 +1278,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761356901, "lastModified": 1759629535,
"narHash": "sha256-YDySchURSJrS1P8zuzmFqypUS7shY6//0e0JiMZeLSI=", "narHash": "sha256-VIXcJ2ahRgoqIUySwAz3r5mtITO2dp6tXGCVKVW6FmA=",
"owner": "fufexan", "owner": "fufexan",
"repo": "nix-gaming", "repo": "nix-gaming",
"rev": "a8635e459ff96acbd156a8de613b99d9d6b3676a", "rev": "df388c42b54714bd121796a9cec9322b7fa2894e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1346,21 +1331,6 @@
} }
}, },
"nixpkgs-lib": { "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": { "locked": {
"lastModified": 1751159883, "lastModified": 1751159883,
"narHash": "sha256-urW/Ylk9FIfvXfliA1ywh75yszAbiTEVgpPeinFyVZo=", "narHash": "sha256-urW/Ylk9FIfvXfliA1ywh75yszAbiTEVgpPeinFyVZo=",
@@ -1375,22 +1345,6 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_10": {
"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"
}
},
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1758690382, "lastModified": 1758690382,
@@ -1409,11 +1363,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1757745802, "lastModified": 1759147044,
"narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=", "narHash": "sha256-3ZPFytJOcLjTChljeaGgoaNj+tOqzgEpqZAvRe3bU90=",
"owner": "NixOS", "owner": "PedroHLC",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1", "rev": "18e83bbe13aa50992777832b52bd0e0d8585fb3b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1424,22 +1378,6 @@
} }
}, },
"nixpkgs_4": { "nixpkgs_4": {
"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_5": {
"locked": { "locked": {
"lastModified": 1753250450, "lastModified": 1753250450,
"narHash": "sha256-i+CQV2rPmP8wHxj0aq4siYyohHwVlsh40kV89f3nw1s=", "narHash": "sha256-i+CQV2rPmP8wHxj0aq4siYyohHwVlsh40kV89f3nw1s=",
@@ -1455,39 +1393,39 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_5": {
"locked": {
"lastModified": 1740560979,
"narHash": "sha256-Vr3Qi346M+8CjedtbyUevIGDZW8LcA1fTG0ugPY/Hic=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "5135c59491985879812717f4c9fea69604e7f26f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_6": { "nixpkgs_6": {
"locked": { "locked": {
"lastModified": 1759381078, "lastModified": 1759381078,
"narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
"owner": "nixos", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "NixOS",
"ref": "nixos-unstable", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs_7": { "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": { "locked": {
"lastModified": 1754243818, "lastModified": 1754243818,
"narHash": "sha256-sEPw2W01UPf0xNGnMGNZIaE1XHkk7O+lLLetYEXVZHk=", "narHash": "sha256-sEPw2W01UPf0xNGnMGNZIaE1XHkk7O+lLLetYEXVZHk=",
@@ -1503,13 +1441,13 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_9": { "nixpkgs_8": {
"locked": { "locked": {
"lastModified": 1761114652, "lastModified": 1759381078,
"narHash": "sha256-f/QCJM/YhrV/lavyCVz8iU3rlZun6d+dAiC3H+CDle4=", "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "01f116e4df6a15f4ccdffb1bcd41096869fb385c", "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1519,20 +1457,36 @@
"type": "github" "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": { "nvf": {
"inputs": { "inputs": {
"flake-compat": "flake-compat_5", "flake-compat": "flake-compat_5",
"flake-parts": "flake-parts_6", "flake-parts": "flake-parts_5",
"mnw": "mnw", "mnw": "mnw",
"nixpkgs": "nixpkgs_10", "nixpkgs": "nixpkgs_9",
"systems": "systems_5" "systems": "systems_5"
}, },
"locked": { "locked": {
"lastModified": 1761112426, "lastModified": 1759469269,
"narHash": "sha256-fa3fIyXP3xQhsPaZX4WsFwPM9g64EMOucfDEC4o8Nwc=", "narHash": "sha256-DP833ejGUNRRHsJOB3WRTaWWXLNucaDga2ju/fGe+sc=",
"owner": "notashelf", "owner": "notashelf",
"repo": "nvf", "repo": "nvf",
"rev": "9b3e7bcf68ace2f07eb7478c40e45ce79332482b", "rev": "e48638aef3a95377689de0ef940443c64f870a09",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1551,11 +1505,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760663237, "lastModified": 1758108966,
"narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=", "narHash": "sha256-ytw7ROXaWZ7OfwHrQ9xvjpUWeGVm86pwnEd1QhzawIo=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37", "rev": "54df955a695a84cd47d4a43e08e1feaf90b1fd9b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1648,7 +1602,7 @@
"chaotic": "chaotic", "chaotic": "chaotic",
"fenix": "fenix", "fenix": "fenix",
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat_2",
"flake-parts": "flake-parts_3", "flake-parts": "flake-parts_2",
"fonts": "fonts", "fonts": "fonts",
"git-hooks": "git-hooks", "git-hooks": "git-hooks",
"hardware": "hardware", "hardware": "hardware",
@@ -1661,7 +1615,7 @@
"hyprpaper": "hyprpaper", "hyprpaper": "hyprpaper",
"lanzaboote": "lanzaboote", "lanzaboote": "lanzaboote",
"nix-gaming": "nix-gaming", "nix-gaming": "nix-gaming",
"nixpkgs": "nixpkgs_9", "nixpkgs": "nixpkgs_8",
"nvf": "nvf", "nvf": "nvf",
"systems": "systems_6", "systems": "systems_6",
"treefmt-nix": "treefmt-nix", "treefmt-nix": "treefmt-nix",
@@ -1672,11 +1626,11 @@
"rust-analyzer-src": { "rust-analyzer-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1761322849, "lastModified": 1759601486,
"narHash": "sha256-KzRamhMnHTBEbYM0lZqozwc9BEYOTBMxVyAtDyiRq3s=", "narHash": "sha256-ZywfLIFtRr907us1tONwUJLeg3ssO4D01XBFHx7RdAo=",
"owner": "rust-lang", "owner": "rust-lang",
"repo": "rust-analyzer", "repo": "rust-analyzer",
"rev": "51236f731456f305bac2b48682f8e1fa3032c989", "rev": "4ae99f0150c94f4bdf7192b4447f512ece3546fd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1694,11 +1648,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761273263, "lastModified": 1759458749,
"narHash": "sha256-6d6ojnu6A6sVxIjig8OL6E1T8Ge9st3YGgVwg5MOY+Q=", "narHash": "sha256-WKnbJnm1B2+TO2ZUudgS39EzecQeLl4/bnRtd3y46LI=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "28405834d4fdd458d28e123fae4db148daecec6f", "rev": "bbc3a8ae797d1700e57a4f4bcc4e79af727d4138",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1715,11 +1669,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759631821, "lastModified": 1740623427,
"narHash": "sha256-V8A1L0FaU/aSXZ1QNJScxC12uP4hANeRBgI4YdhHeRM=", "narHash": "sha256-3SdPQrZoa4odlScFDUHd4CUPQ/R1gtH4Mq9u8CBiK8M=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "1d7cbdaad90f8a5255a89a6eddd8af24dc89cafe", "rev": "d342e8b5fd88421ff982f383c853f0fc78a847ab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1861,11 +1815,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761311587, "lastModified": 1758728421,
"narHash": "sha256-Msq86cR5SjozQGCnC6H8C+0cD4rnx91BPltZ9KK613Y=", "narHash": "sha256-ySNJ008muQAds2JemiyrWYbwbG+V7S5wg3ZVKGHSFu8=",
"owner": "numtide", "owner": "numtide",
"repo": "treefmt-nix", "repo": "treefmt-nix",
"rev": "2eddae033e4e74bf581c2d1dfa101f9033dbd2dc", "rev": "5eda4ee8121f97b218f7cc73f5172098d458f1d1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1876,7 +1830,7 @@
}, },
"tuirun": { "tuirun": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_7", "flake-parts": "flake-parts_6",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
@@ -1949,11 +1903,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1760713634, "lastModified": 1755354946,
"narHash": "sha256-5HXelmz2x/uO26lvW7MudnadbAfoBnve4tRBiDVLtOM=", "narHash": "sha256-zdov5f/GcoLQc9qYIS1dUTqtJMeDqmBmo59PAxze6e4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland", "repo": "xdg-desktop-portal-hyprland",
"rev": "753bbbdf6a052994da94062e5b753288cef28dfb", "rev": "a10726d6a8d0ef1a0c645378f983b6278c42eaa0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1969,11 +1923,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1761276110, "lastModified": 1759590499,
"narHash": "sha256-k9HfFWBxM7DNGrahC+IZtB8DcZyBW2uUW0HktffX640=", "narHash": "sha256-EBToRzqe5WMz4DQyxOp9/CP+rWjdaZ2EUwbItfNf3VI=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "f0b40ea6601bf74bdfb4bfeb2e969122b0115ea7", "rev": "6e606c8bfa6a88209488790388b1005bc489fa66",
"revCount": 140, "revCount": 136,
"type": "git", "type": "git",
"url": "https://git.sr.ht/~canasta/zen-browser-flake" "url": "https://git.sr.ht/~canasta/zen-browser-flake"
}, },

View File

@@ -1,7 +1,8 @@
{ {
description = "cnix nix"; description = "cnix nix";
outputs = inputs: outputs =
inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } { inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ systems = [
"x86_64-linux" "x86_64-linux"
@@ -16,11 +17,13 @@
./fmt-hooks.nix ./fmt-hooks.nix
]; ];
perSystem = { perSystem =
{
config, config,
pkgs, pkgs,
... ...
}: { }:
{
devShells.default = pkgs.mkShell { devShells.default = pkgs.mkShell {
packages = [ packages = [
pkgs.git pkgs.git
@@ -53,7 +56,11 @@
}; };
authentik = { authentik = {
url = "github:nix-community/authentik-nix/version/2025.8.3"; url = "github:nix-community/authentik-nix";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-parts.follows = "flake-parts";
};
}; };
flake-compat.url = "github:edolstra/flake-compat"; flake-compat.url = "github:edolstra/flake-compat";

View File

@@ -73,8 +73,8 @@
enable = false; enable = false;
}; };
hyprland = { hyprland = {
enable = true; enable = false;
withUWSM = true; withUWSM = false;
}; };
inkscape = { inkscape = {
enable = false; enable = false;
@@ -86,7 +86,7 @@
enable = true; enable = true;
}; };
niri = { niri = {
enable = false; enable = true;
}; };
pkgs = { pkgs = {
enable = true; enable = true;

View File

@@ -10,7 +10,7 @@
name = "DP-3"; name = "DP-3";
width = 2560; width = 2560;
height = 1440; height = 1440;
refreshRate = "143.99"; refreshRate = 240;
position = "0x0"; position = "0x0";
transform = 0; transform = 0;
bitDepth = 10; bitDepth = 10;
@@ -20,7 +20,7 @@
name = "HDMI-A-1"; name = "HDMI-A-1";
width = 1920; width = 1920;
height = 1080; height = 1080;
refreshRate = "60"; refreshRate = 60;
position = "2560x0"; position = "2560x0";
# transform = 3; # transform = 3;
workspace = "5"; workspace = "5";
@@ -29,7 +29,7 @@
name = "eDP-1"; name = "eDP-1";
width = 1920; width = 1920;
height = 1200; height = 1200;
refreshRate = "60"; refreshRate = 60;
workspace = "1"; workspace = "1";
} }
]; ];

View File

@@ -8,7 +8,7 @@
{ {
flake.nixosConfigurations = flake.nixosConfigurations =
let let
clib = import ../lib inputs.nixpkgs.lib; cLib = import ../lib inputs.nixpkgs.lib;
userConfig = "${self}/home"; userConfig = "${self}/home";
systemConfig = "${self}/system"; systemConfig = "${self}/system";
hostConfig = "${self}/hosts"; hostConfig = "${self}/hosts";
@@ -24,6 +24,7 @@
specialArgs = { specialArgs = {
inherit inherit
cLib
inputs inputs
outputs outputs
self self
@@ -36,20 +37,17 @@
smodPath smodPath
; ;
}; };
specialArgsWithClib = specialArgs // {
inherit clib;
};
in in
{ {
kima = nixosSystem { kima = nixosSystem {
specialArgs = specialArgsWithClib; inherit specialArgs;
modules = [ modules = [
./kima ./kima
"${self}/nix" "${self}/nix"
{ {
home-manager = { home-manager = {
users.cnst.imports = homeImports."cnst@kima"; users.cnst.imports = homeImports."cnst@kima";
extraSpecialArgs = specialArgsWithClib; extraSpecialArgs = specialArgs;
}; };
} }
self.nixosModules.nixos self.nixosModules.nixos
@@ -59,14 +57,14 @@
]; ];
}; };
bunk = nixosSystem { bunk = nixosSystem {
specialArgs = specialArgsWithClib; inherit specialArgs;
modules = [ modules = [
./bunk ./bunk
"${self}/nix" "${self}/nix"
{ {
home-manager = { home-manager = {
users.cnst.imports = homeImports."cnst@bunk"; users.cnst.imports = homeImports."cnst@bunk";
extraSpecialArgs = specialArgsWithClib; extraSpecialArgs = specialArgs;
}; };
} }
self.nixosModules.nixos self.nixosModules.nixos
@@ -99,14 +97,14 @@
]; ];
}; };
toothpc = nixosSystem { toothpc = nixosSystem {
specialArgs = specialArgsWithClib; inherit specialArgs;
modules = [ modules = [
./toothpc ./toothpc
"${self}/nix" "${self}/nix"
{ {
home-manager = { home-manager = {
users.toothpick.imports = homeImports."toothpick@toothpc"; users.toothpick.imports = homeImports."toothpick@toothpc";
extraSpecialArgs = specialArgsWithClib; extraSpecialArgs = specialArgs;
}; };
} }
self.nixosModules.nixos self.nixosModules.nixos

View File

@@ -29,13 +29,6 @@
}; };
network = { network = {
enable = true; enable = true;
nameservers = [
"192.168.88.1"
"192.168.88.69"
];
search = [
"taila7448a.ts.net"
];
interfaces = { interfaces = {
"eno1" = { "eno1" = {
allowedTCPPorts = [ allowedTCPPorts = [
@@ -73,7 +66,7 @@
}; };
}; };
gamescope = { gamescope = {
enable = false; enable = true;
}; };
gimp = { gimp = {
enable = true; enable = true;
@@ -82,8 +75,8 @@
enable = false; enable = false;
}; };
hyprland = { hyprland = {
enable = true; enable = false;
withUWSM = true; withUWSM = false;
}; };
inkscape = { inkscape = {
enable = false; enable = false;
@@ -98,7 +91,7 @@
enable = true; enable = true;
}; };
niri = { niri = {
enable = false; enable = true;
}; };
pkgs = { pkgs = {
enable = true; enable = true;
@@ -223,7 +216,7 @@
flags = "--performance"; flags = "--performance";
}; };
tailscale = { tailscale = {
enable = true; enable = false;
}; };
udisks = { udisks = {
enable = true; enable = true;

View File

@@ -10,7 +10,7 @@
name = "DP-3"; name = "DP-3";
width = 2560; width = 2560;
height = 1440; height = 1440;
refreshRate = "143.99"; refreshRate = 240;
position = "0x0"; position = "0x0";
transform = 0; transform = 0;
bitDepth = 10; bitDepth = 10;
@@ -20,7 +20,7 @@
name = "HDMI-A-1"; name = "HDMI-A-1";
width = 1920; width = 1920;
height = 1080; height = 1080;
refreshRate = "60"; refreshRate = 60;
position = "2560x0"; position = "2560x0";
transform = 3; transform = 3;
workspace = "5"; workspace = "5";
@@ -29,7 +29,7 @@
name = "eDP-1"; name = "eDP-1";
width = 1920; width = 1920;
height = 1200; height = 1200;
refreshRate = "60"; refreshRate = 60;
workspace = "1"; workspace = "1";
} }
]; ];

View File

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

View File

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

View File

@@ -3,34 +3,77 @@
enable = true; enable = true;
email = "adam@cnst.dev"; email = "adam@cnst.dev";
domain = "cnix.dev"; domain = "cnix.dev";
ip = "192.168.88.14";
user = "share"; user = "share";
group = "share"; group = "share";
uid = 994; uid = 994;
gid = 993; gid = 993;
infra = { traefik = {
enable = true;
};
gitea = {
enable = true;
};
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;
};
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 = { authentik = {
enable = true; enable = true;
url = "auth.cnst.dev"; url = "auth.cnst.dev";
port = 9000;
cloudflared = { cloudflared = {
tunnelId = "b66f9368-db9e-4302-8b48-527cda34a635"; tunnelId = "b66f9368-db9e-4302-8b48-527cda34a635";
credentialsFile = config.age.secrets.authentikCloudflared.path; credentialsFile = config.age.secrets.authentikCloudflared.path;
}; };
}; };
traefik = { nextcloud = {
enable = true;
};
headscale = {
enable = true;
port = 8581;
};
tailscale = {
enable = true;
};
unbound = {
enable = true; enable = true;
adminpassFile = config.age.secrets.nextcloudAdminPass.path;
}; };
fail2ban = { fail2ban = {
enable = true; enable = true;
@@ -41,242 +84,19 @@
enable = true; enable = true;
interface = "enp6s0"; interface = "enp6s0";
}; };
gluetun = {
enable = true;
};
podman = { podman = {
enable = true; 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 = { qbittorrent = {
enable = true; enable = true;
subdomain = "qbt";
exposure = "local";
port = 8080; port = 8080;
homepage = {
name = "qBittorrent";
description = "Torrent client";
icon = "qbittorrent.svg";
category = "Downloads";
};
}; };
slskd = { slskd = {
enable = true; enable = true;
subdomain = "slskd";
exposure = "local";
port = 5030;
homepage = {
name = "Soulseek";
description = "Web-based Soulseek client";
icon = "slskd.svg";
category = "Downloads";
};
}; };
pihole = { pihole = {
enable = true; enable = true;
subdomain = "pihole";
exposure = "local";
port = 8053; port = 8053;
homepage = {
name = "PiHole";
description = "Adblocking and DNS service";
icon = "pi-hole.svg";
category = "Services";
path = "/admin";
};
}; };
}; };
}; };

View File

@@ -4,10 +4,6 @@
username = "cnst"; username = "cnst";
mail = "adam@cnst.dev"; mail = "adam@cnst.dev";
sshUser = "sobotka"; sshUser = "sobotka";
domains = {
local = "cnix.dev";
public = "cnst.dev";
};
}; };
}; };
} }

View File

@@ -10,7 +10,7 @@
name = "DVI-D-1"; name = "DVI-D-1";
width = 1920; width = 1920;
height = 1080; height = 1080;
refreshRate = "144"; refreshRate = 144;
position = "0x0"; position = "0x0";
transform = 0; transform = 0;
workspace = "1"; workspace = "1";

View File

@@ -1,26 +0,0 @@
{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;
}

View File

@@ -123,6 +123,27 @@
server = { server = {
imports = [ imports = [
./server ./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
]; ];
}; };
settings = { settings = {

View File

@@ -15,16 +15,17 @@ in
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = [ pkgs.gh ]; home.packages = [ pkgs.gh ];
programs = { programs.git = {
git = {
enable = true; enable = true;
settings = { userName = osConfig.settings.accounts.username;
# user.signingkey = "${config.home.homeDirectory}/.ssh/id_ed25519.pub"; userEmail = osConfig.settings.accounts.mail;
user = { delta = {
name = osConfig.settings.accounts.username; enable = true;
email = osConfig.settings.accounts.mail; options.dark = true;
signingkey = "${config.home.homeDirectory}/.config/git/allowed_signers";
}; };
extraConfig = {
# user.signingkey = "${config.home.homeDirectory}/.ssh/id_ed25519.pub";
user.signingkey = "${config.home.homeDirectory}/.config/git/allowed_signers";
signing = { signing = {
format = lib.mkDefault "ssh"; format = lib.mkDefault "ssh";
key = "${config.home.homeDirectory}/.ssh/id_ed25519"; key = "${config.home.homeDirectory}/.ssh/id_ed25519";
@@ -55,14 +56,6 @@ in
".jj" ".jj"
]; ];
}; };
delta = {
enableGitIntegration = true;
enable = true;
options.dark = true;
};
};
xdg.configFile."git/allowed_signers".text = '' xdg.configFile."git/allowed_signers".text = ''
${osConfig.settings.accounts.mail} namespaces="git" ${osConfig.settings.accounts.sshKey} ${osConfig.settings.accounts.mail} namespaces="git" ${osConfig.settings.accounts.sshKey}
''; '';

View File

@@ -1,18 +1,26 @@
{ {
inputs,
pkgs,
lib, lib,
osConfig, osConfig,
clib, cLib,
... ...
}: let }:
inherit (lib) mkIf; let
inherit (lib) mkIf mkEnableOption;
cfg = osConfig.nixos.programs.hyprland; cfg = osConfig.nixos.programs.hyprland;
hyprlockFlake = inputs.hyprlock.packages.${pkgs.system}.hyprlock;
# hyprlockPkg = pkgs.hyprlock;
#
bg = osConfig.settings.theme.background; bg = osConfig.settings.theme.background;
inherit (clib.theme.bgs) resolve; inherit (cLib.theme.bgs) resolve;
in { in
{
config = mkIf cfg.enable { config = mkIf cfg.enable {
programs.hyprlock = { programs.hyprlock = {
enable = true; enable = true;
package = hyprlockFlake;
settings = { settings = {
general = { general = {
# disable_loading_bar = true; # disable_loading_bar = true;

View File

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

View File

@@ -10,7 +10,7 @@
"group/system" "group/system"
], ],
"modules-center": [ "modules-center": [
"hyprland/workspaces" "niri/workspaces"
], ],
"modules-right": [ "modules-right": [
"custom/progress", "custom/progress",
@@ -126,13 +126,9 @@
"all-outputs": false, "all-outputs": false,
"format": "{icon}", "format": "{icon}",
"format-icons": { "format-icons": {
"1": "1", "urgent": "",
"2": "2", "visible": "",
"3": "3", "empty": ""
"4": "4",
"5": "5",
"active": "_",
"default": "_"
}, },
"on-click": "activate", "on-click": "activate",
"show-special": false, "show-special": false,

View File

@@ -28,8 +28,8 @@ tooltip label {
margin: 0 0px; margin: 0 0px;
background-color: transparent; background-color: transparent;
color: #fbf1c7; color: #fbf1c7;
border-top: 2px solid transparent; border-top: 3px solid transparent;
border-bottom: 2px solid transparent; border-bottom: 3px solid transparent;
} }
#workspaces button:hover { #workspaces button:hover {
@@ -45,7 +45,7 @@ tooltip label {
background-image: url("assets/button.svg"); background-image: url("assets/button.svg");
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 24px 20px; background-size: 18px 15px;
} }
#custom-trayicon { #custom-trayicon {

View File

@@ -1,14 +1,22 @@
{ {
osConfig, osConfig,
lib, lib,
pkgs,
inputs,
... ...
}: let }:
let
inherit (lib) mkIf; inherit (lib) mkIf;
cfg = osConfig.nixos.programs.hyprland; cfg = osConfig.nixos.programs.hyprland;
in {
hypridleFlake = inputs.hypridle.packages.${pkgs.system}.hypridle;
# hypridlePkg = pkgs.hypridle;
in
{
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.hypridle = { services.hypridle = {
enable = true; enable = true;
package = hypridleFlake;
settings = { settings = {
general = { general = {
lock_cmd = "hyprlock"; lock_cmd = "hyprlock";

View File

@@ -1,14 +1,18 @@
{ {
lib, lib,
pkgs,
inputs,
osConfig, osConfig,
clib, cLib,
... ...
}: let }:
let
inherit (lib) mkIf; inherit (lib) mkIf;
cfg = osConfig.nixos.programs.hyprland; cfg = osConfig.nixos.programs.hyprland;
hyprpaperFlake = inputs.hyprpaper.packages.${pkgs.system}.default;
bg = osConfig.settings.theme.background; bg = osConfig.settings.theme.background;
bgs = clib.theme.bgs; bgs = cLib.theme.bgs;
monitorMappings = [ monitorMappings = [
{ {
@@ -28,10 +32,12 @@
bg = bg.primary; bg = bg.primary;
} }
]; ];
in { in
{
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.hyprpaper = { services.hyprpaper = {
enable = true; enable = true;
package = hyprpaperFlake;
settings = { settings = {
ipc = "on"; ipc = "on";

View File

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

View File

@@ -2,29 +2,20 @@
config, config,
lib, lib,
... ...
}: let }:
inherit let
(lib) inherit (lib)
mkIf mkIf
mkEnableOption mkEnableOption
mkOption mkOption
types types
; ;
cfg = config.nixos.hardware.network; cfg = config.nixos.hardware.network;
in { in
{
options = { options = {
nixos.hardware.network = { nixos.hardware.network = {
enable = mkEnableOption "Enable the custom networking module"; enable = mkEnableOption "Enable the custom networking module";
nameservers = mkOption {
type = types.listOf types.str;
default = [];
description = "The list of nameservers ";
};
search = mkOption {
type = types.listOf types.str;
default = [];
description = "Domain search paths";
};
interfaces = mkOption { interfaces = mkOption {
type = types.attrsOf ( type = types.attrsOf (
types.submodule { types.submodule {
@@ -64,8 +55,6 @@ in {
networking = { networking = {
networkmanager.enable = true; networkmanager.enable = true;
nftables.enable = true; nftables.enable = true;
nameservers = cfg.nameservers;
search = cfg.search;
firewall = { firewall = {
enable = true; enable = true;
inherit (cfg) interfaces; inherit (cfg) interfaces;

View File

@@ -37,9 +37,9 @@ in
}; };
gestures = { gestures = {
# workspace_swipe = true; workspace_swipe = true;
workspace_swipe_distance = 400; workspace_swipe_distance = 400;
# workspace_swipe_fingers = 3; workspace_swipe_fingers = 3;
workspace_swipe_cancel_ratio = 0.2; workspace_swipe_cancel_ratio = 0.2;
workspace_swipe_min_speed_to_force = 5; workspace_swipe_min_speed_to_force = 5;
workspace_swipe_direction_lock = true; workspace_swipe_direction_lock = true;

View File

@@ -49,6 +49,20 @@ in
"$mod, P, pseudo," "$mod, P, pseudo,"
"$mod, J, togglesplit," "$mod, J, togglesplit,"
"$mod, C, exec, hyprctl dispatch exec copyq toggle" "$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, 1, movetoworkspace, 1"
"$mod SHIFT, 2, movetoworkspace, 2" "$mod SHIFT, 2, movetoworkspace, 2"
"$mod SHIFT, 3, movetoworkspace, 3" "$mod SHIFT, 3, movetoworkspace, 3"
@@ -61,30 +75,6 @@ in
"$mod SHIFT, 0, movetoworkspace, 10" "$mod SHIFT, 0, movetoworkspace, 10"
"CTRL SHIFT, Escape, exec, ${runOnce "resources"}" "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" ",XF86AudioLowerVolume, exec, volume-control.sh --dec"
",XF86AudioRaiseVolume, exec, volume-control.sh --inc" ",XF86AudioRaiseVolume, exec, volume-control.sh --inc"
",XF86AudioMute, exec, volume-control.sh --toggle" ",XF86AudioMute, exec, volume-control.sh --toggle"
@@ -109,7 +99,7 @@ in
(mkIf (host == "kima") { (mkIf (host == "kima") {
programs.hyprland.settings = { programs.hyprland.settings = {
"$terminal" = "alacritty"; "$terminal" = "ghostty";
"$browser" = "zen"; "$browser" = "zen";
"$browserinc" = "zen --private-window"; "$browserinc" = "zen --private-window";
"$mod" = "SUPER"; "$mod" = "SUPER";
@@ -121,7 +111,7 @@ in
(mkIf (host == "bunk") { (mkIf (host == "bunk") {
programs.hyprland.settings = { programs.hyprland.settings = {
"$terminal" = "alacritty"; "$terminal" = "foot";
"$browser" = "zen"; "$browser" = "zen";
"$browserinc" = "zen --private-window"; "$browserinc" = "zen --private-window";
"$mod" = "ALT_L"; "$mod" = "ALT_L";

View File

@@ -21,7 +21,7 @@ in
let let
resolution = resolution =
if m.width != null && m.height != null then if m.width != null && m.height != null then
"${toString m.width}x${toString m.height}@${m.refreshRate}" "${toString m.width}x${toString m.height}@${toString m.refreshRate}"
else else
"preferred"; "preferred";

View File

@@ -78,10 +78,10 @@ in
openssl openssl
xmrig xmrig
ocl-icd ocl-icd
dig
] ]
(mkIf cfg.common.enable [ (mkIf cfg.common.enable [
qt6.full
swappy swappy
wayfreeze wayfreeze
imagemagick imagemagick
@@ -96,6 +96,9 @@ in
]) ])
(mkIf cfg.desktop.enable [ (mkIf cfg.desktop.enable [
protonup
winetricks
wine
geekbench geekbench
unigine-heaven unigine-heaven
]) ])
@@ -106,13 +109,15 @@ in
(mkIf cfg.server.enable [ (mkIf cfg.server.enable [
nvtopPackages.intel nvtopPackages.intel
nvtopPackages.amd
dig
helix helix
zfs
zfstools zfstools
]) ])
(mkIf cfg.dev.enable [ (mkIf cfg.dev.enable [
# lldb_20 # some biuld error atm # lldb_20 # some biuld error atm
sqlite
gemini-cli gemini-cli
nfs-utils nfs-utils
gcc gcc
@@ -139,6 +144,7 @@ in
prettierd prettierd
# php84Packages.php-cs-fixer # php84Packages.php-cs-fixer
shfmt shfmt
luaformatter
black black
]) ])
]; ];

View File

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

View File

@@ -16,10 +16,14 @@ in
services.kanata = { services.kanata = {
enable = true; enable = true;
package = pkgs.kanata-with-cmd; package = pkgs.kanata-with-cmd;
keyboards.default = { keyboards.hhkbse = {
extraDefCfg = '' extraDefCfg = ''
process-unmapped-keys yes process-unmapped-keys yes
''; '';
devices = [
"/dev/input/by-id/usb-PFU_Limited_HHKB-Hybrid-event-kbd"
"/dev/input/event2"
];
config = builtins.readFile (./. + "/hhkbse.kbd"); config = builtins.readFile (./. + "/hhkbse.kbd");
}; };
}; };

View File

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

View File

@@ -1,24 +1,21 @@
{ {
config, config,
lib, lib,
pkgs,
self, self,
... ...
}: let }: let
unit = "authentik"; unit = "authentik";
cfg = config.server.infra.${unit}; cfg = config.server.${unit};
srv = config.server.infra; srv = config.server;
in { in {
options.server.infra.${unit} = { options.server.${unit} = {
enable = lib.mkEnableOption { enable = lib.mkEnableOption {
description = "Enable ${unit}"; description = "Enable ${unit}";
}; };
url = lib.mkOption { url = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "auth.${srv.www.url}"; default = "auth.${srv.www.domain}";
};
port = lib.mkOption {
type = lib.types.port;
description = "The local port the service runs on";
}; };
cloudflared = { cloudflared = {
credentialsFile = lib.mkOption { credentialsFile = lib.mkOption {
@@ -34,11 +31,21 @@ in {
example = "00000000-0000-0000-0000-000000000000"; example = "00000000-0000-0000-0000-000000000000";
}; };
}; };
homepage = { homepage.name = lib.mkOption {
name = "Authentik"; type = lib.types.str;
description = "An open-source IdP for modern SSO"; default = "Authentik";
icon = "authentik.svg"; };
category = "Services"; 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";
}; };
}; };
@@ -46,18 +53,24 @@ in {
age.secrets = { age.secrets = {
authentikEnv = { authentikEnv = {
file = "${self}/secrets/authentikEnv.age"; file = "${self}/secrets/authentikEnv.age";
owner = "authentik";
group = "authentik";
mode = "0400";
}; };
authentikCloudflared = { authentikCloudflared = {
file = "${self}/secrets/authentikCloudflared.age"; file = "${self}/secrets/authentikCloudflared.age";
owner = "authentik";
group = "authentik";
mode = "0400";
}; };
}; };
server.infra = { server = {
fail2ban = { fail2ban = lib.mkIf cfg.enable {
jails = { jails = {
authentik = { authentik = {
serviceName = "authentik"; serviceName = "authentik";
failRegex = ''^.*Username or password is incorrect.*IP:\s*<HOST>''; failRegex = "^.*Username or password is incorrect.*IP:\s*<HOST>";
}; };
}; };
}; };
@@ -90,6 +103,7 @@ in {
middlewares = { middlewares = {
authentik = { authentik = {
forwardAuth = { forwardAuth = {
# tls.insecureSkipVerify = true;
address = "https://localhost:9443/outpost.goauthentik.io/auth/traefik"; address = "https://localhost:9443/outpost.goauthentik.io/auth/traefik";
trustForwardHeader = true; trustForwardHeader = true;
authResponseHeaders = [ authResponseHeaders = [
@@ -105,6 +119,7 @@ in {
"X-authentik-meta-app" "X-authentik-meta-app"
"X-authentik-meta-version" "X-authentik-meta-version"
]; ];
timeout = "10s";
}; };
}; };
}; };
@@ -120,7 +135,7 @@ in {
routers = { routers = {
auth = { auth = {
entryPoints = ["websecure"]; entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`) && PathPrefix(`/outpost.goauthentik.io/`)"; rule = "Host(`${cfg.url}`) || HostRegexp(`{subdomain:[a-z0-9]+}.${srv.www.url}`) && PathPrefix(`/outpost.goauthentik.io/`)";
service = "auth"; service = "auth";
tls.certResolver = "letsencrypt"; tls.certResolver = "letsencrypt";
}; };

View File

@@ -0,0 +1,62 @@
{
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"];
};
};
};
};
};
};
}

View File

@@ -1,16 +1,101 @@
{ {
self,
lib, lib,
config,
pkgs,
... ...
}: let }: let
clib = import "${self}/lib/server" {inherit lib;}; hardDrives = [
in { "/dev/disk/by-label/data"
imports = [
{
_module.args.clib = clib;
}
./options.nix
./infra
./services
]; ];
inherit (lib) mkOption types;
cfg = config.server;
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
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"
];
};
};
};
} }

View File

@@ -5,9 +5,9 @@
pkgs, pkgs,
... ...
}: let }: let
cfg = config.server.infra.fail2ban; cfg = config.server.fail2ban;
in { in {
options.server.infra.fail2ban = { options.server.fail2ban = {
enable = lib.mkEnableOption { enable = lib.mkEnableOption {
description = "Enable cloudflare fail2ban"; description = "Enable cloudflare fail2ban";
}; };
@@ -30,28 +30,14 @@ in {
example = "vaultwarden"; example = "vaultwarden";
type = lib.types.str; type = lib.types.str;
}; };
_groupsre = lib.mkOption {
type = lib.types.lines;
example = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
default = "";
};
failRegex = lib.mkOption { failRegex = lib.mkOption {
type = lib.types.lines; type = lib.types.str;
example = '' example = "Login failed from IP: <HOST>";
^Login failed from IP: <HOST>$
^Two-factor challenge failed from <HOST>$
'';
}; };
ignoreRegex = lib.mkOption { ignoreRegex = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = ""; default = "";
}; };
datePattern = lib.mkOption {
type = lib.types.str;
default = "";
example = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
description = "Optional datepattern line for the fail2ban filter.";
};
maxRetry = lib.mkOption { maxRetry = lib.mkOption {
type = lib.types.int; type = lib.types.int;
default = 3; default = 3;
@@ -61,7 +47,6 @@ in {
); );
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.fail2ban = { services.fail2ban = {
enable = true; enable = true;
@@ -90,17 +75,10 @@ in {
environment.etc = lib.attrsets.mergeAttrsList [ environment.etc = lib.attrsets.mergeAttrsList [
(lib.attrsets.mapAttrs' ( (lib.attrsets.mapAttrs' (
name: value: (lib.nameValuePair "fail2ban/filter.d/${name}.conf" { name: value: (lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
text = text = ''
''
[Definition] [Definition]
failregex = ${value.failRegex} failregex = ${value.failRegex}
ignoreregex = ${value.ignoreRegex} ignoreregex = ${value.ignoreRegex}
''
+ lib.optionalString (value.datePattern != "") ''
datepattern = ${value.datePattern}
''
+ lib.optionalString (value._groupsre != "") ''
_groupsre = ${value._groupsre}
''; '';
}) })
) )

View File

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

View File

@@ -0,0 +1,236 @@
{
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 = true;
};
}
];
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"];
};
};
};
};
};
};
};
}

View File

@@ -1,14 +0,0 @@
{
imports = [
./authentik
./fail2ban
./headscale
./keepalived
./podman
./postgres
./tailscale
./traefik
./unbound
./www
];
}

View File

@@ -1,83 +0,0 @@
{
config,
lib,
self,
...
}:
with lib; let
cfg = config.server.infra.headscale;
srv = config.server.infra;
in {
options.server.infra.headscale = {
enable = mkEnableOption "Enable headscale server configuration";
url = lib.mkOption {
type = lib.types.str;
default = "hs.${srv.www.url}";
};
port = lib.mkOption {
type = lib.types.port;
description = "The local port the service runs on";
};
};
config = mkIf cfg.enable {
# age.secrets.sobotkaHsAuth.file = "${self}/secrets/sobotkaHsAuth.age";
services = {
headscale = {
enable = true;
port = cfg.port;
settings = {
server_url = "http://${cfg.url}";
prefixes = {
v4 = "100.64.0.0/10";
v6 = "fd7a:115c:a1e0::/48";
allocation = "random";
};
dns = {
magic_dns = true;
base_domain = "ts.cnst.dev";
override_local_dns = true;
nameservers = {
global = [
"192.168.88.1"
"192.168.88.69"
];
split = {
};
};
# oidc = {
# issuer = "https://auth.cnst.dev/oauth2/openid/headscale";
# client_id = "headscale";
# client_secret_path = config.age.secrets.headscaleSecret.path;
# };
};
};
};
traefik = {
dynamicConfigOptions = {
http = {
services = {
auth.loadBalancer.servers = [
{
url = "http://localhost:8581";
}
];
};
routers = {
headscale = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)";
service = "headscale";
tls.certResolver = "letsencrypt";
};
};
};
};
};
};
};
}

View File

@@ -1,6 +0,0 @@
---
filenames:
- /var/log/traefik/access.log
poll_without_inotify: true
labels:
type: traefik

View File

@@ -1,194 +0,0 @@
{
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"
];
};
})
];
};
}

View File

@@ -1,26 +0,0 @@
{
config,
lib,
self,
...
}:
with lib; let
cfg = config.server.infra.tailscale;
in {
options.server.infra.tailscale = {
enable = mkEnableOption "Enable tailscale server configuration";
};
config = mkIf cfg.enable {
age.secrets.sobotkaTsAuth.file = "${self}/secrets/sobotkaTsAuth.age";
services.tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
authKeyFile = config.age.secrets.sobotkaTsAuth.path;
extraSetFlags = [
"--advertise-exit-node"
];
};
};
}

View File

@@ -1,183 +0,0 @@
{
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";
# };
# };
# };
# };
};
};
};
};
};
}

View File

@@ -0,0 +1,66 @@
{
config,
lib,
pkgs,
...
}: let
service = "jellyfin";
cfg = config.server.${service};
srv = config.server;
in {
options.server.${service} = {
enable = lib.mkEnableOption {
description = "Enable ${service}";
};
configDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
};
url = lib.mkOption {
type = lib.types.str;
default = "jellyfin.${srv.domain}";
};
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.${service} = {
enable = true;
user = srv.user;
group = srv.group;
};
environment.systemPackages = with pkgs; [
jellyfin-ffmpeg
];
services.traefik = {
dynamicConfigOptions = {
http = {
services.jellyfin.loadBalancer.servers = [{url = "http://127.0.0.1:8096";}];
routers = {
jellyfin = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)";
service = "jellyfin";
tls.certResolver = "letsencrypt";
# middlewares = ["authentik"];
};
};
};
};
};
};
}

View File

@@ -0,0 +1,61 @@
{
config,
lib,
...
}: let
service = "jellyseerr";
srv = config.server;
cfg = config.server.${service};
in {
options.server.${service} = {
enable = lib.mkEnableOption {
description = "Enable ${service}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${service}.${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.${service} = {
enable = true;
port = cfg.port;
};
services.traefik = {
dynamicConfigOptions = {
http = {
services.jellyseerr.loadBalancer.servers = [{url = "http://127.0.0.1:${toString cfg.port}";}];
routers = {
jellyseerr = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)";
service = "jellyseerr";
tls.certResolver = "letsencrypt";
# middlewares = ["authentik"];
};
};
};
};
};
};
}

View File

@@ -3,24 +3,27 @@
config, config,
self, self,
... ...
}: let }:
let
unit = "keepalived"; unit = "keepalived";
cfg = config.server.infra.${unit}; cfg = config.server.${unit};
hostCfg = hostname: hostCfg =
if hostname == "sobotka" hostname:
then { if hostname == "sobotka" then
{
ip = "192.168.88.14"; ip = "192.168.88.14";
priority = 20; priority = 20;
state = "MASTER"; state = "MASTER";
} }
else if hostname == "ziggy" else if hostname == "ziggy" then
then { {
ip = "192.168.88.12"; ip = "192.168.88.12";
priority = 10; priority = 10;
state = "BACKUP"; 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; _self = hostCfg config.networking.hostName;
@@ -31,8 +34,9 @@
# Remove self from peers # Remove self from peers
peers = builtins.filter (ip: ip != _self.ip) allPeers; peers = builtins.filter (ip: ip != _self.ip) allPeers;
in { in
options.server.infra.${unit} = { {
options.server.${unit} = {
enable = lib.mkEnableOption { enable = lib.mkEnableOption {
description = "Enable ${unit}"; description = "Enable ${unit}";
}; };

View File

@@ -0,0 +1,62 @@
{
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"];
};
};
};
};
};
};
}

View File

@@ -0,0 +1,64 @@
{
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"];
};
};
};
};
};
};
};
}

View File

@@ -6,30 +6,64 @@
... ...
}: let }: let
unit = "nextcloud"; unit = "nextcloud";
cfg = config.server.services.${unit}; cfg = config.server.${unit};
srv = config.server; srv = config.server;
in { 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 { config = lib.mkIf cfg.enable {
age.secrets = { age.secrets = {
nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age"; nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age";
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age"; nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
}; };
server.infra.fail2ban.jails.nextcloud = { server.fail2ban = lib.mkIf config.server.fail2ban.enable {
serviceName = "${unit}"; jails = {
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)''; nextcloud = {
failRegex = '' serviceName = "phpfpm-nextcloud";
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed: failRegex = "^.*Login failed:.*(Remote IP: <HOST>).*$";
^\{%(_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 = { services = {
${unit} = { ${unit} = {
enable = true; enable = true;
package = pkgs.nextcloud32; package = pkgs.nextcloud31;
hostName = "nextcloud"; hostName = "nextcloud";
configureRedis = true; configureRedis = true;
caching = { caching = {
@@ -67,7 +101,7 @@ in {
dbhost = "/run/postgresql"; dbhost = "/run/postgresql";
dbname = "nextcloud"; dbname = "nextcloud";
adminuser = "cnst"; adminuser = "cnst";
adminpassFile = config.age.secrets.nextcloudAdminPass.path; adminpassFile = cfg.adminpassFile;
}; };
}; };
@@ -86,9 +120,21 @@ in {
forceSSL = false; 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.infra.postgresql.databases = [ server.postgresql.databases = [
{ {
database = "nextcloud"; database = "nextcloud";
} }

View File

@@ -1,180 +0,0 @@
{
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"
];
};
};
};
}

View File

@@ -0,0 +1,321 @@
{
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:latest";
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"
];
};
})
];
};
}

View File

@@ -7,10 +7,10 @@
}: let }: let
inherit (lib) types mkOption; inherit (lib) types mkOption;
cfg = config.server.infra.postgresql; cfg = config.server.postgresql;
in { in {
options = { options = {
server.infra.postgresql = { server.postgresql = {
upgradeTargetPackage = mkOption { upgradeTargetPackage = mkOption {
type = types.nullOr types.package; type = types.nullOr types.package;
default = null; default = null;

View File

@@ -7,7 +7,7 @@
}: let }: let
inherit (lib) types mkOption; inherit (lib) types mkOption;
cfg = config.server.infra.postgresql; cfg = config.server.postgresql;
database = {name, ...}: { database = {name, ...}: {
options = { options = {
@@ -31,7 +31,7 @@
}; };
in { in {
options = { options = {
server.infra.postgresql = { server.postgresql = {
databases = mkOption { databases = mkOption {
type = types.listOf (types.submodule database); type = types.listOf (types.submodule database);
default = []; default = [];

View File

@@ -0,0 +1,80 @@
{
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"];
};
};
};
};
};
};
};
}

View File

@@ -0,0 +1,62 @@
{
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"];
};
};
};
};
};
};
}

View File

@@ -1,17 +0,0 @@
{
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;
};
};
}

View File

@@ -1,19 +0,0 @@
{
imports = [
./bazarr
./flaresolverr
./gitea
./homepage-dashboard
./jellyfin
./jellyseerr
./lidarr
./n8n
./nextcloud
./ollama
./prowlarr
./radarr
./sonarr
./uptime-kuma
./vaultwarden
];
}

View File

@@ -1,16 +0,0 @@
{
config,
lib,
...
}: let
unit = "flaresolverr";
cfg = config.server.services.${unit};
in {
config = lib.mkIf cfg.enable {
services = {
${unit} = {
enable = true;
};
};
};
}

View File

@@ -1,94 +0,0 @@
{
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;
};
};
};
};
}

View File

@@ -1,227 +0,0 @@
{
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";
};
};
}
];
}
];
};
};
};
}

View File

@@ -1,21 +0,0 @@
{
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
];
};
}

View File

@@ -1,15 +0,0 @@
{
config,
lib,
...
}: let
unit = "jellyseerr";
cfg = config.server.services.${unit};
in {
config = lib.mkIf cfg.enable {
services.${unit} = {
enable = true;
port = cfg.port;
};
};
}

View File

@@ -1,17 +0,0 @@
{
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;
};
};
}

View File

@@ -1,17 +0,0 @@
{
config,
lib,
...
}: let
unit = "n8n";
cfg = config.server.services.${unit};
in {
config = lib.mkIf cfg.enable {
services = {
n8n = {
enable = true;
openFirewall = true;
};
};
};
}

View File

@@ -1,28 +0,0 @@
{
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";
};
};
};
}

View File

@@ -1,16 +0,0 @@
{
config,
lib,
...
}: let
unit = "prowlarr";
cfg = config.server.services.${unit};
in {
config = lib.mkIf cfg.enable {
services = {
${unit} = {
enable = true;
};
};
};
}

View File

@@ -1,17 +0,0 @@
{
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;
};
};
}

View File

@@ -1,17 +0,0 @@
{
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;
};
};
}

View File

@@ -1,16 +0,0 @@
{
config,
lib,
...
}: let
unit = "uptime-kuma";
cfg = config.server.services.${unit};
in {
config = lib.mkIf cfg.enable {
services = {
${unit} = {
enable = true;
};
};
};
}

View File

@@ -1,59 +0,0 @@
# 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";
};
};
}

View File

@@ -0,0 +1,62 @@
{
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"];
};
};
};
};
};
};
}

View File

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

View File

@@ -5,25 +5,7 @@
... ...
}: let }: let
unit = "unbound"; unit = "unbound";
cfg = config.server.infra.${unit}; cfg = config.server.${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);
revParts = lib.lists.reverseList (lib.splitString "." srv.ip);
revName = lib.concatStringsSep "." revParts;
localPTRs = ["${revName}.in-addr.arpa. PTR traefik.${srv.domain}"];
hostIp = hostname: hostIp = hostname:
if hostname == "ziggy" if hostname == "ziggy"
@@ -32,12 +14,11 @@
then "192.168.88.14" then "192.168.88.14"
else throw "No IP defined for host ${hostname}"; else throw "No IP defined for host ${hostname}";
in { in {
options.server.infra.${unit} = { options.server.${unit} = {
enable = lib.mkEnableOption { enable = lib.mkEnableOption {
description = "Enable ${unit}"; description = "Enable ${unit}";
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services = { services = {
# resolved.enable = lib.mkForce false; # resolved.enable = lib.mkForce false;
@@ -116,10 +97,6 @@ in {
"255.255.255.255/32" "255.255.255.255/32"
"2001:db8::/32" "2001:db8::/32"
]; ];
local-data = localARecords;
# Example PTR entry: "14.88.168.192.in-addr.arpa. PTR traefik.cnix.dev."
# local-data-ptr = localPTRs;
}; };
}; };
}; };

View File

@@ -0,0 +1,62 @@
{
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"];
};
};
};
};
};
};
};
}

View File

@@ -0,0 +1,89 @@
# 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: <HOST>. Username: <F-USER>.*</F-USER>.$";
};
};
};
};
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 = false;
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}";
};
};
};
};
}

View File

@@ -1,13 +1,22 @@
{ {
lib, lib,
config, config,
pkgs,
self, self,
... ...
}: let }:
inherit (lib) mkIf mkEnableOption mkOption types; let
cfg = config.server.infra.www; inherit (lib)
in { mkOption
options.server.infra.www = { mkEnableOption
mkIf
types
;
cfg = config.server.www;
srv = config.server;
in
{
options.server.www = {
enable = mkEnableOption { enable = mkEnableOption {
description = "Enable personal website"; description = "Enable personal website";
}; };
@@ -18,12 +27,6 @@ in {
Public domain name to be used to access the server services via Traefik reverse proxy 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 = { cloudflared = {
credentialsFile = lib.mkOption { credentialsFile = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@@ -45,13 +48,13 @@ in {
wwwCloudflared.file = "${self}/secrets/wwwCloudflared.age"; wwwCloudflared.file = "${self}/secrets/wwwCloudflared.age";
}; };
server.infra = { server = {
fail2ban = { fail2ban = lib.mkIf config.server.www.enable {
jails = { jails = {
nginx-404 = { nginx-404 = {
serviceName = "nginx"; serviceName = "nginx";
failRegex = ''^.*\[error\].*directory index of.* is forbidden.*client: <HOST>.*$''; failRegex = ''^.*\[error\].*directory index of.* is forbidden.*client: <HOST>.*$'';
ignoreRegex = ''''; ignoreRegex = "";
maxRetry = 5; maxRetry = 5;
}; };
}; };

View File

@@ -2,7 +2,8 @@
lib, lib,
config, config,
... ...
}: let }:
let
inherit (lib) mkOption types; inherit (lib) mkOption types;
sshKeys = { sshKeys = {
@@ -15,14 +16,14 @@
keyName = config.settings.accounts.sshUser or null; keyName = config.settings.accounts.sshUser or null;
selectedKey = selectedKey =
if keyName != null if keyName != null then
then
lib.attrByPath [ lib.attrByPath [
keyName keyName
] (builtins.abort "No SSH key defined for hostname/key '${toString keyName}'") ] (builtins.abort "No SSH key defined for hostname/key '${toString keyName}'") sshKeys
sshKeys else
else builtins.abort "No accounts.sshUser provided, cannot select SSH key."; builtins.abort "No accounts.sshUser provided, cannot select SSH key.";
in { in
{
options.settings.accounts = { options.settings.accounts = {
username = mkOption { username = mkOption {
type = types.str; type = types.str;
@@ -45,21 +46,5 @@ in {
default = null; default = null;
description = "Optional override for selecting an SSH key by name"; 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";
};
};
};
};
}; };
} }

View File

@@ -21,8 +21,8 @@ in
example = 1080; example = 1080;
}; };
refreshRate = mkOption { refreshRate = mkOption {
type = types.str; type = types.int;
default = "60"; default = 60;
}; };
transform = mkOption { transform = mkOption {
type = types.int; type = types.int;

View File

@@ -4,8 +4,5 @@
allowUnfree = true; allowUnfree = true;
input-fonts.acceptLicense = true; input-fonts.acceptLicense = true;
}; };
overlays = [
];
}; };
} }

View File

@@ -5,7 +5,9 @@
"aarch64-linux" "aarch64-linux"
]; ];
perSystem = {pkgs, ...}: { perSystem =
{ pkgs, ... }:
{
packages = { packages = {
# instant repl with automatic flake loading # instant repl with automatic flake loading
repl = pkgs.callPackage ./repl { }; repl = pkgs.callPackage ./repl { };

View File

@@ -1,11 +0,0 @@
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><>

View File

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

Binary file not shown.

View File

@@ -1,11 +0,0 @@
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>;

View File

@@ -48,7 +48,6 @@ in {
"homepageEnvironment.age".publicKeys = kima ++ sobotka; "homepageEnvironment.age".publicKeys = kima ++ sobotka;
"cloudflareFirewallApiKey.age".publicKeys = kima ++ sobotka; "cloudflareFirewallApiKey.age".publicKeys = kima ++ sobotka;
"vaultwardenCloudflared.age".publicKeys = kima ++ sobotka; "vaultwardenCloudflared.age".publicKeys = kima ++ sobotka;
"giteaCloudflared.age".publicKeys = kima ++ sobotka;
"nextcloudCloudflared.age".publicKeys = kima ++ sobotka; "nextcloudCloudflared.age".publicKeys = kima ++ sobotka;
"nextcloudAdminPass.age".publicKeys = kima ++ sobotka; "nextcloudAdminPass.age".publicKeys = kima ++ sobotka;
"cloudflareDnsApiToken.age".publicKeys = kima ++ sobotka; "cloudflareDnsApiToken.age".publicKeys = kima ++ sobotka;
@@ -62,9 +61,6 @@ in {
"traefikEnv.age".publicKeys = kima ++ sobotka; "traefikEnv.age".publicKeys = kima ++ sobotka;
"wwwCloudflared.age".publicKeys = kima ++ sobotka; "wwwCloudflared.age".publicKeys = kima ++ sobotka;
"authentikCloudflared.age".publicKeys = kima ++ sobotka; "authentikCloudflared.age".publicKeys = kima ++ sobotka;
"sobotkaTsAuth.age".publicKeys = kima ++ sobotka;
"mikrotikSecret.age".publicKeys = kima ++ sobotka;
"crowdsecApi.age".publicKeys = kima ++ sobotka;
# Ziggy-specific # Ziggy-specific
"cloudflareDnsCredentialsZiggy.age".publicKeys = kima ++ ziggy; "cloudflareDnsCredentialsZiggy.age".publicKeys = kima ++ ziggy;

View File

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

Binary file not shown.

View File

@@ -11,7 +11,7 @@
enable = true; enable = true;
}; };
chromium = { chromium = {
enable = true; enable = false;
}; };
discord = { discord = {
enable = true; enable = true;