feat(IP): migrate to traefik and authentik, remove dead code

This commit is contained in:
2025-09-23 18:13:28 +02:00
parent b752781064
commit 86624f362d
37 changed files with 1202 additions and 803 deletions

350
flake.lock generated
View File

@@ -74,6 +74,54 @@
"type": "github"
}
},
"authentik": {
"inputs": {
"authentik-src": "authentik-src",
"flake-compat": "flake-compat",
"flake-parts": [
"flake-parts"
],
"flake-utils": "flake-utils",
"napalm": "napalm",
"nixpkgs": [
"nixpkgs"
],
"pyproject-build-systems": "pyproject-build-systems",
"pyproject-nix": "pyproject-nix",
"systems": "systems_3",
"uv2nix": "uv2nix"
},
"locked": {
"lastModified": 1758177015,
"narHash": "sha256-PCUWdbaxayY3YfSjVlyddBMYoGvSaRysd5AmZ8gqSFs=",
"owner": "nix-community",
"repo": "authentik-nix",
"rev": "4c626ed84cc0f1278bfba0f534efd6cba2788d75",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "authentik-nix",
"type": "github"
}
},
"authentik-src": {
"flake": false,
"locked": {
"lastModified": 1758035356,
"narHash": "sha256-DkvxDwHCfSqEpZ9rRXNR8MP0Mz/y1kHAr38exrHQ39c=",
"owner": "goauthentik",
"repo": "authentik",
"rev": "680feaefa17934471a6b33ebc35caf5b64120404",
"type": "github"
},
"original": {
"owner": "goauthentik",
"ref": "version/2025.8.3",
"repo": "authentik",
"type": "github"
}
},
"chaotic": {
"inputs": {
"flake-schemas": "flake-schemas",
@@ -83,11 +131,11 @@
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1758033778,
"narHash": "sha256-oQH2wLOWLFHXT3NE+gcsFOX+Pq40bKjlOH1xw0wcmT8=",
"lastModified": 1758540151,
"narHash": "sha256-5emcCJqkkpInzhyCGUXXcktPjNQInRHzCvHzP/2XspY=",
"owner": "chaotic-cx",
"repo": "nyx",
"rev": "b3efa297b9c6a9e55a44f3b6905d55f80738704f",
"rev": "c2bc079a4179295eee766d00b9ae264e68e13db9",
"type": "github"
},
"original": {
@@ -142,11 +190,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1758177713,
"narHash": "sha256-4Mesi0sOxCzrwnFHeAhL/vv1K1Wcwsl4D9duQ7ndYS8=",
"lastModified": 1758523473,
"narHash": "sha256-8zsEI6eLilOSNQ9Mp6NL1XG7J7TQSqWB9Rsux0TCfqk=",
"owner": "nix-community",
"repo": "fenix",
"rev": "60316bdc00603b483992560baa14841e42e58a7b",
"rev": "2176d4c89be105a792122b66afc412dcce275b0d",
"type": "github"
},
"original": {
@@ -156,6 +204,7 @@
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
@@ -171,7 +220,6 @@
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
@@ -203,6 +251,22 @@
}
},
"flake-compat_4": {
"flake": false,
"locked": {
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_5": {
"flake": false,
"locked": {
"lastModified": 1751685974,
@@ -354,6 +418,27 @@
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%3D0.1.5.tar.gz"
}
},
"flake-utils": {
"inputs": {
"systems": [
"authentik",
"systems"
]
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"fonts": {
"inputs": {
"flake-parts": "flake-parts_3",
@@ -483,11 +568,11 @@
"rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1758204752,
"narHash": "sha256-tgblfdzdM3XAzYHHvA9GX9SR2P8NG2IzewmfnRmTUxg=",
"lastModified": 1758548657,
"narHash": "sha256-Y4PRLA9vpgR6olcHrcdQcPjZ2ukb4L3xnS5xJLS+ugU=",
"owner": "helix-editor",
"repo": "helix",
"rev": "0ae37dc52ba715100893c327414bcb1a1924a4c3",
"rev": "37fe42d05d4d65e0c8112a10cc40cfbdc95e8a3c",
"type": "github"
},
"original": {
@@ -503,11 +588,11 @@
]
},
"locked": {
"lastModified": 1758207369,
"narHash": "sha256-BG7GlXo5moXtrFSCqnkIb1Q00szOZXTj5Dx7NmWgves=",
"lastModified": 1758545873,
"narHash": "sha256-0VP5cVd6DyibHNPC/IJ5Ut+KuNYUeKmr5ltzf+IcpjA=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "b5698ed57db7ee7da5e93df2e6bbada91c88f3ce",
"rev": "de5369834ff1f75246c46be89ef993392e961c26",
"type": "github"
},
"original": {
@@ -545,11 +630,11 @@
]
},
"locked": {
"lastModified": 1757920978,
"narHash": "sha256-Mv16aegXLulgyDunijP6SPFJNm8lSXb2w3Q0X+vZ9TY=",
"lastModified": 1758464306,
"narHash": "sha256-i56XRXqjwJRdVYmpzVUQ0ktqBBHqNzQHQMQvFRF/acQ=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "11cc5449c50e0e5b785be3dfcb88245232633eb8",
"rev": "939e91e1cff1f99736c5b02529658218ed819a2a",
"type": "github"
},
"original": {
@@ -603,11 +688,11 @@
]
},
"locked": {
"lastModified": 1757542864,
"narHash": "sha256-8i9tsVoOmLQDHJkNgzJWnmxYFGkJNsSndimYpCoqmoA=",
"lastModified": 1758192433,
"narHash": "sha256-CR6RnqEJSTiFgA6KQY4TTLUWbZ8RBnb+hxQqesuQNzQ=",
"owner": "hyprwm",
"repo": "hyprgraphics",
"rev": "aa9d14963b94186934fd0715d9a7f0f2719e64bb",
"rev": "c44e749dd611521dee940d00f7c444ee0ae4cfb7",
"type": "github"
},
"original": {
@@ -692,15 +777,15 @@
"hyprwayland-scanner": "hyprwayland-scanner_2",
"nixpkgs": "nixpkgs_6",
"pre-commit-hooks": "pre-commit-hooks",
"systems": "systems_3",
"systems": "systems_4",
"xdph": "xdph"
},
"locked": {
"lastModified": 1758198304,
"narHash": "sha256-UbPAu5MRqAaDT3/seC64GyVjUDsFhGaNZFMPtuE0RI4=",
"lastModified": 1758542519,
"narHash": "sha256-dAMZsDFYTSqPkBbQHvQoCCiyX7Z07nyPKThKq8yFq9c=",
"owner": "hyprwm",
"repo": "hyprland",
"rev": "059ec60e9f32e4d7a21c0bc15b010bcb30a1303b",
"rev": "70a7047ee175d2e7fca1575d50a3738ac40fd2c6",
"type": "github"
},
"original": {
@@ -717,11 +802,11 @@
]
},
"locked": {
"lastModified": 1758055182,
"narHash": "sha256-0TCggLT5bUMpJYoA8+EXs8Qu+D9sTVe6eOmsNetH8OI=",
"lastModified": 1758531979,
"narHash": "sha256-iRv5afKzuu6SkwztqMwZ33161CzBJsyeRHp0uviN9TI=",
"owner": "hyprwm",
"repo": "contrib",
"rev": "9e73a0e753251fbc6e987bd13324886dc6ca8f9a",
"rev": "de79078fd59140067e53cd00ebdf17f96ce27846",
"type": "github"
},
"original": {
@@ -835,11 +920,11 @@
]
},
"locked": {
"lastModified": 1757508108,
"narHash": "sha256-bTYedtQFqqVBAh42scgX7+S3O6XKLnT6FTC6rpmyCCc=",
"lastModified": 1757694755,
"narHash": "sha256-j+w5QUUr2QT/jkxgVKecGYV8J7fpzXCMgzEEr6LG9ug=",
"owner": "hyprwm",
"repo": "hyprland-qtutils",
"rev": "119bcb9aa742658107b326c50dcd24ab59b309b7",
"rev": "5ffdfc13ed03df1dae5084468d935f0a3f2c9a4c",
"type": "github"
},
"original": {
@@ -1100,7 +1185,7 @@
"lanzaboote": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat_3",
"flake-compat": "flake-compat_4",
"flake-parts": "flake-parts_4",
"nixpkgs": "nixpkgs_7",
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
@@ -1135,6 +1220,32 @@
"type": "github"
}
},
"napalm": {
"inputs": {
"flake-utils": [
"authentik",
"flake-utils"
],
"nixpkgs": [
"authentik",
"nixpkgs"
]
},
"locked": {
"lastModified": 1725806412,
"narHash": "sha256-lGZjkjds0p924QEhm/r0BhAxbHBJE1xMOldB/HmQH04=",
"owner": "willibutz",
"repo": "napalm",
"rev": "b492440d9e64ae20736d3bec5c7715ffcbde83f5",
"type": "github"
},
"original": {
"owner": "willibutz",
"ref": "avoid-foldl-stack-overflow",
"repo": "napalm",
"type": "github"
}
},
"niri": {
"inputs": {
"niri-stable": "niri-stable",
@@ -1145,11 +1256,11 @@
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
},
"locked": {
"lastModified": 1758186479,
"narHash": "sha256-UdC6KXSnt1QfEigiP6TtS3R9TIqPEFJegPoTcjhC4SY=",
"lastModified": 1758445565,
"narHash": "sha256-eTC6gRzq1yXYy+HhDJ4IBdOvHCfTBRxMis6AdPCjxUQ=",
"owner": "sodiboo",
"repo": "niri-flake",
"rev": "b399b939d7b980b52cbd739a7d44f07017c8572e",
"rev": "b98cd80e3bdd67a636291ce91953eec1c1b25dae",
"type": "github"
},
"original": {
@@ -1178,11 +1289,11 @@
"niri-unstable": {
"flake": false,
"locked": {
"lastModified": 1758183971,
"narHash": "sha256-rZpQqXa9LIwWulScUEHMqtcJqlidx5OfEfEr/iVC+AM=",
"lastModified": 1758370095,
"narHash": "sha256-1/QacQbqle22hjwS1QjLlTpmIdSRYLKZ+NLHvo1r95E=",
"owner": "YaLTeR",
"repo": "niri",
"rev": "d9648e6bde1d2fc4a568dec93ba65c11073192a3",
"rev": "6451d6be4f7046bd3d02bbe22dc50bb7b94235a5",
"type": "github"
},
"original": {
@@ -1201,11 +1312,11 @@
]
},
"locked": {
"lastModified": 1757814419,
"narHash": "sha256-wmlDAkOrwX9cvhXQa7wekGr/5G6SfE2D5KlvuvSEEXc=",
"lastModified": 1758420014,
"narHash": "sha256-a7IGWXPRppgXMRpBosBl2Afr5DICt21ogeZL45uVkX0=",
"owner": "fufexan",
"repo": "nix-gaming",
"rev": "17db183a6a2ba1217bbfc123b47d4b5ee70b256a",
"rev": "cd931e08409954b2e3595b1532039f8052dd8198",
"type": "github"
},
"original": {
@@ -1270,11 +1381,11 @@
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1758070117,
"narHash": "sha256-uLwwHFCZnT1c3N3biVe/0hCkag2GSrf9+M56+Okf+WY=",
"lastModified": 1758346548,
"narHash": "sha256-afXE7AJ7MY6wY1pg/Y6UPHNYPy5GtUKeBkrZZ/gC71E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e9b7f2ff62b35f711568b1f0866243c7c302028d",
"rev": "b2a3852bd078e68dd2b3dfa8c00c67af1f0a7d20",
"type": "github"
},
"original": {
@@ -1318,11 +1429,11 @@
},
"nixpkgs_3": {
"locked": {
"lastModified": 1758029758,
"narHash": "sha256-fKqsvznISxVSBo6aaiGGXMRiBG4IIuV3sSySxx80pcQ=",
"lastModified": 1758479131,
"narHash": "sha256-KTCOYqnEUYSdk+DychTkXkOqgxYO2mLp9AzAw5mwAxA=",
"owner": "PedroHLC",
"repo": "nixpkgs",
"rev": "4eb5897225c3d7e78a0b9d1542197ee7c8d270a5",
"rev": "94700b18eb20d3ec71e3f6cd32e30d03648664ba",
"type": "github"
},
"original": {
@@ -1366,11 +1477,11 @@
},
"nixpkgs_6": {
"locked": {
"lastModified": 1757487488,
"narHash": "sha256-zwE/e7CuPJUWKdvvTCB7iunV4E/+G0lKfv4kk/5Izdg=",
"lastModified": 1758198701,
"narHash": "sha256-7To75JlpekfUmdkUZewnT6MoBANS0XVypW6kjUOXQwc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ab0f3607a6c7486ea22229b92ed2d355f1482ee0",
"rev": "0147c2f1d54b30b5dd6d4a8c8542e8d7edf93b5d",
"type": "github"
},
"original": {
@@ -1398,11 +1509,11 @@
},
"nixpkgs_8": {
"locked": {
"lastModified": 1758035966,
"narHash": "sha256-qqIJ3yxPiB0ZQTT9//nFGQYn8X/PBoJbofA7hRKZnmE=",
"lastModified": 1758277210,
"narHash": "sha256-iCGWf/LTy+aY0zFu8q12lK8KuZp7yvdhStehhyX1v8w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8d4ddb19d03c65a36ad8d189d001dc32ffb0306b",
"rev": "8eaee110344796db060382e15d3af0a9fc396e0e",
"type": "github"
},
"original": {
@@ -1414,11 +1525,11 @@
},
"nixpkgs_9": {
"locked": {
"lastModified": 1758035966,
"narHash": "sha256-qqIJ3yxPiB0ZQTT9//nFGQYn8X/PBoJbofA7hRKZnmE=",
"lastModified": 1758277210,
"narHash": "sha256-iCGWf/LTy+aY0zFu8q12lK8KuZp7yvdhStehhyX1v8w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8d4ddb19d03c65a36ad8d189d001dc32ffb0306b",
"rev": "8eaee110344796db060382e15d3af0a9fc396e0e",
"type": "github"
},
"original": {
@@ -1430,18 +1541,18 @@
},
"nvf": {
"inputs": {
"flake-compat": "flake-compat_4",
"flake-compat": "flake-compat_5",
"flake-parts": "flake-parts_5",
"mnw": "mnw",
"nixpkgs": "nixpkgs_10",
"systems": "systems_4"
"systems": "systems_5"
},
"locked": {
"lastModified": 1757955071,
"narHash": "sha256-owSpkt551cIqDDk5iHesdEus9REFeOIY3rY4C5ZPm/Y=",
"lastModified": 1758271661,
"narHash": "sha256-ENqd2/33uP5vB44ClDjjAV+J78oF8q1er4QUZuT8Z7g=",
"owner": "notashelf",
"repo": "nvf",
"rev": "1bd9fc116420db4c1156819d61df5d5312e1bbea",
"rev": "b7571df4d6e9ac08506a738ddceeec0b141751b0",
"type": "github"
},
"original": {
@@ -1452,7 +1563,7 @@
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-compat": "flake-compat_3",
"gitignore": "gitignore_2",
"nixpkgs": [
"hyprland",
@@ -1460,11 +1571,11 @@
]
},
"locked": {
"lastModified": 1757588530,
"narHash": "sha256-tJ7A8mID3ct69n9WCvZ3PzIIl3rXTdptn/lZmqSS95U=",
"lastModified": 1758108966,
"narHash": "sha256-ytw7ROXaWZ7OfwHrQ9xvjpUWeGVm86pwnEd1QhzawIo=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "b084b2c2b6bc23e83bbfe583b03664eb0b18c411",
"rev": "54df955a695a84cd47d4a43e08e1feaf90b1fd9b",
"type": "github"
},
"original": {
@@ -1499,13 +1610,64 @@
"type": "github"
}
},
"pyproject-build-systems": {
"inputs": {
"nixpkgs": [
"authentik",
"nixpkgs"
],
"pyproject-nix": [
"authentik",
"pyproject-nix"
],
"uv2nix": [
"authentik",
"uv2nix"
]
},
"locked": {
"lastModified": 1757296493,
"narHash": "sha256-6nzSZl28IwH2Vx8YSmd3t6TREHpDbKlDPK+dq1LKIZQ=",
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"rev": "5b8e37fe0077db5c1df3a5ee90a651345f085d38",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"type": "github"
}
},
"pyproject-nix": {
"inputs": {
"nixpkgs": [
"authentik",
"nixpkgs"
]
},
"locked": {
"lastModified": 1757246327,
"narHash": "sha256-6pNlGhwOIMfhe/RLjHdpXveKS4FyLHvlGe+KtjDild4=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "8d77f342d66ad1601cdb9d97e9388b69f64d4c8e",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"type": "github"
}
},
"root": {
"inputs": {
"agenix": "agenix",
"anyrun": "anyrun",
"authentik": "authentik",
"chaotic": "chaotic",
"fenix": "fenix",
"flake-compat": "flake-compat",
"flake-compat": "flake-compat_2",
"flake-parts": "flake-parts_2",
"fonts": "fonts",
"git-hooks": "git-hooks",
@@ -1522,7 +1684,7 @@
"nix-gaming": "nix-gaming",
"nixpkgs": "nixpkgs_9",
"nvf": "nvf",
"systems": "systems_5",
"systems": "systems_6",
"treefmt-nix": "treefmt-nix",
"tuirun": "tuirun",
"zen-browser": "zen-browser"
@@ -1531,11 +1693,11 @@
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1757362324,
"narHash": "sha256-/PAhxheUq4WBrW5i/JHzcCqK5fGWwLKdH6/Lu1tyS18=",
"lastModified": 1758437297,
"narHash": "sha256-bfB1uXmAc8ECK5fj8YIMNvzukNdDS30J1zCKSAavg1c=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "9edc9cbe5d8e832b5864e09854fa94861697d2fd",
"rev": "e7d7cb415a3cca2b09aae9c6bbe06d129a511cba",
"type": "github"
},
"original": {
@@ -1553,11 +1715,11 @@
]
},
"locked": {
"lastModified": 1757930296,
"narHash": "sha256-Z9u5VszKs8rfEvg2AsFucWEjl7wMtAln9l1b78cfBh4=",
"lastModified": 1758422215,
"narHash": "sha256-JvF5SXhp1wBHbfEVAWgJCDVSO8iknfDqXfqMch5YWg0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "09442765a05c2ca617c20ed68d9613da92a2d96b",
"rev": "6f3988eb5885f1e2efa874a480d91de09a7f9f0b",
"type": "github"
},
"original": {
@@ -1654,6 +1816,21 @@
}
},
"systems_4": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
"owner": "nix-systems",
"repo": "default-linux",
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default-linux",
"type": "github"
}
},
"systems_5": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
@@ -1668,7 +1845,7 @@
"type": "github"
}
},
"systems_5": {
"systems_6": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
@@ -1683,7 +1860,7 @@
"type": "github"
}
},
"systems_6": {
"systems_7": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
@@ -1724,7 +1901,7 @@
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_6"
"systems": "systems_7"
},
"locked": {
"lastModified": 1735478319,
@@ -1740,6 +1917,31 @@
"url": "https://git.sr.ht/~canasta/tuirun"
}
},
"uv2nix": {
"inputs": {
"nixpkgs": [
"authentik",
"nixpkgs"
],
"pyproject-nix": [
"authentik",
"pyproject-nix"
]
},
"locked": {
"lastModified": 1757925761,
"narHash": "sha256-7Hwz0vfHuFqCo5v7Q07GQgLBWuPvZCuf/5/pk4NoADg=",
"owner": "pyproject-nix",
"repo": "uv2nix",
"rev": "780494c40895bb7419a73d942bee326291e80b3b",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "uv2nix",
"type": "github"
}
},
"xdph": {
"inputs": {
"hyprland-protocols": [

View File

@@ -1,9 +1,8 @@
{
description = "cnix nix";
outputs =
inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
outputs = inputs:
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
systems = [
"x86_64-linux"
"aarch64-linux"
@@ -17,21 +16,23 @@
./fmt-hooks.nix
];
perSystem =
{ config, pkgs, ... }:
{
devShells.default = pkgs.mkShell {
packages = [
pkgs.git
config.packages.repl
];
name = "dots";
env.DIRENV_LOG_FORMAT = "";
shellHook = ''
${config.pre-commit.installationScript}
'';
};
perSystem = {
config,
pkgs,
...
}: {
devShells.default = pkgs.mkShell {
packages = [
pkgs.git
config.packages.repl
];
name = "dots";
env.DIRENV_LOG_FORMAT = "";
shellHook = ''
${config.pre-commit.installationScript}
'';
};
};
};
inputs = {
@@ -51,6 +52,14 @@
inputs.nixpkgs-lib.follows = "nixpkgs";
};
authentik = {
url = "github:nix-community/authentik-nix";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-parts.follows = "flake-parts";
};
};
flake-compat.url = "github:edolstra/flake-compat";
# Hyprland environment

View File

@@ -4,113 +4,111 @@
homeImports,
self,
...
}:
{
flake.nixosConfigurations =
let
cLib = import ../lib inputs.nixpkgs.lib;
userConfig = "${self}/home";
systemConfig = "${self}/system";
hostConfig = "${self}/hosts";
}: {
flake.nixosConfigurations = let
cLib = import ../lib inputs.nixpkgs.lib;
userConfig = "${self}/home";
systemConfig = "${self}/system";
hostConfig = "${self}/hosts";
cnstConfig = "${self}/users/cnst";
toothpickConfig = "${self}/users/toothpick";
cnstConfig = "${self}/users/cnst";
toothpickConfig = "${self}/users/toothpick";
umodPath = "${self}/modules/home";
smodPath = "${self}/modules/system";
umodPath = "${self}/modules/home";
smodPath = "${self}/modules/system";
inherit (inputs.nixpkgs.lib) nixosSystem;
inherit (self) outputs;
inherit (inputs.nixpkgs.lib) nixosSystem;
inherit (self) outputs;
specialArgs = {
inherit
cLib
inputs
outputs
self
userConfig
systemConfig
hostConfig
cnstConfig
toothpickConfig
umodPath
smodPath
;
};
in
{
kima = nixosSystem {
inherit specialArgs;
modules = [
./kima
"${self}/nix"
{
home-manager = {
users.cnst.imports = homeImports."cnst@kima";
extraSpecialArgs = specialArgs;
};
}
self.nixosModules.nixos
self.nixosModules.settings
inputs.chaotic.nixosModules.default
inputs.agenix.nixosModules.default
];
};
bunk = nixosSystem {
inherit specialArgs;
modules = [
./bunk
"${self}/nix"
{
home-manager = {
users.cnst.imports = homeImports."cnst@bunk";
extraSpecialArgs = specialArgs;
};
}
self.nixosModules.nixos
self.nixosModules.settings
inputs.chaotic.nixosModules.default
inputs.agenix.nixosModules.default
];
};
sobotka = nixosSystem {
inherit specialArgs;
modules = [
./sobotka
"${self}/nix"
self.nixosModules.nixos
self.nixosModules.settings
self.nixosModules.server
inputs.agenix.nixosModules.default
];
};
ziggy = nixosSystem {
inherit specialArgs;
modules = [
./ziggy
"${self}/nix"
self.nixosModules.nixos
self.nixosModules.settings
self.nixosModules.server
inputs.agenix.nixosModules.default
];
};
toothpc = nixosSystem {
inherit specialArgs;
modules = [
./toothpc
"${self}/nix"
{
home-manager = {
users.toothpick.imports = homeImports."toothpick@toothpc";
extraSpecialArgs = specialArgs;
};
}
self.nixosModules.nixos
self.nixosModules.settings
inputs.chaotic.nixosModules.default
inputs.agenix.nixosModules.default
];
};
specialArgs = {
inherit
cLib
inputs
outputs
self
userConfig
systemConfig
hostConfig
cnstConfig
toothpickConfig
umodPath
smodPath
;
};
in {
kima = nixosSystem {
inherit specialArgs;
modules = [
./kima
"${self}/nix"
{
home-manager = {
users.cnst.imports = homeImports."cnst@kima";
extraSpecialArgs = specialArgs;
};
}
self.nixosModules.nixos
self.nixosModules.settings
inputs.chaotic.nixosModules.default
inputs.agenix.nixosModules.default
];
};
bunk = nixosSystem {
inherit specialArgs;
modules = [
./bunk
"${self}/nix"
{
home-manager = {
users.cnst.imports = homeImports."cnst@bunk";
extraSpecialArgs = specialArgs;
};
}
self.nixosModules.nixos
self.nixosModules.settings
inputs.chaotic.nixosModules.default
inputs.agenix.nixosModules.default
];
};
sobotka = nixosSystem {
inherit specialArgs;
modules = [
./sobotka
"${self}/nix"
self.nixosModules.nixos
self.nixosModules.settings
self.nixosModules.server
inputs.agenix.nixosModules.default
inputs.authentik.nixosModules.default
];
};
ziggy = nixosSystem {
inherit specialArgs;
modules = [
./ziggy
"${self}/nix"
self.nixosModules.nixos
self.nixosModules.settings
self.nixosModules.server
inputs.agenix.nixosModules.default
];
};
toothpc = nixosSystem {
inherit specialArgs;
modules = [
./toothpc
"${self}/nix"
{
home-manager = {
users.toothpick.imports = homeImports."toothpick@toothpc";
extraSpecialArgs = specialArgs;
};
}
self.nixosModules.nixos
self.nixosModules.settings
inputs.chaotic.nixosModules.default
inputs.agenix.nixosModules.default
];
};
};
}

0
hosts/sobotka/output Normal file
View File

View File

@@ -3,12 +3,21 @@
enable = true;
email = "adam@cnst.dev";
domain = "cnix.dev";
domainPublic = "cnst.dev";
user = "share";
group = "share";
uid = 994;
gid = 993;
authentik = {
enable = true;
};
traefik = {
enable = true;
};
www = {
enable = true;
url = "cnst.dev";
};
gitea = {
enable = true;
};
@@ -16,7 +25,7 @@
enable = true;
};
acme = {
enable = true;
enable = false;
};
homepage-dashboard = {
enable = true;
@@ -45,15 +54,6 @@
uptime-kuma = {
enable = true;
};
keycloak = {
enable = true;
url = "login.cnst.dev";
dbPasswordFile = config.age.secrets.keycloakDbPasswordFile.path;
cloudflared = {
tunnelId = "590f60f8-baaa-4106-b2d1-43740c79531e";
credentialsFile = config.age.secrets.keycloakCloudflared.path;
};
};
vaultwarden = {
enable = true;
url = "vault.cnst.dev";
@@ -71,9 +71,6 @@
apiKeyFile = config.age.secrets.cloudflareFirewallApiKey.path;
zoneId = "0027acdfb8bbe010f55b676ad8698dfb";
};
syncthing = {
enable = false;
};
keepalived = {
enable = true;
interface = "enp6s0";

View File

@@ -127,14 +127,12 @@
./server/fail2ban
./server/homepage-dashboard
./server/nextcloud
./server/keycloak
./server/vaultwarden
./server/bazarr
./server/prowlarr
./server/lidarr
./server/radarr
./server/sonarr
./server/syncthing
./server/jellyseerr
./server/jellyfin
./server/podman
@@ -143,6 +141,9 @@
./server/keepalived
./server/gitea
./server/postgres
./server/traefik
./server/www
./server/authentik
];
};
settings = {

View File

@@ -74,8 +74,6 @@ in {
wgCredentials.file = "${self}/secrets/wgCredentials.age";
wgSobotkaPrivateKey.file = "${self}/secrets/wgSobotkaPrivateKey.age";
gluetunEnvironment.file = "${self}/secrets/gluetunEnvironment.age";
keycloakCloudflared.file = "${self}/secrets/keycloakCloudflared.age";
keycloakDbPasswordFile.file = "${self}/secrets/keycloakDbPasswordFile.age";
nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age";
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";

View File

@@ -39,16 +39,16 @@ in {
group = config.services.caddy.group;
environmentFile = getCloudflareCredentials config.networking.hostName;
};
# certs.${config.server.domainPublic} = {
# reloadServices = ["nginx.service"];
# domain = "${config.server.domainPublic}";
# extraDomainNames = ["*.${config.server.domainPublic}"];
# dnsProvider = "cloudflare";
# dnsResolver = "1.1.1.1:53";
# dnsPropagationCheck = true;
# group = config.services.nginx.group;
# environmentFile = getCloudflareCredentials config.networking.hostName;
# };
certs.${config.server.www.url} = {
reloadServices = ["caddy.service"];
domain = "${config.server.www.url}";
extraDomainNames = ["*.${config.server.www.url}"];
dnsProvider = "cloudflare";
dnsResolver = "1.1.1.1:53";
dnsPropagationCheck = true;
group = config.services.caddy.group;
environmentFile = getCloudflareCredentials config.networking.hostName;
};
};
services.caddy = {
@@ -67,6 +67,17 @@ in {
redir https://{host}{uri}
'';
};
"http://${config.server.www.url}" = {
extraConfig = ''
redir https://{host}{uri}
'';
};
"http://*.${config.server.www.url}" = {
extraConfig = ''
redir https://{host}{uri}
'';
};
};
};
};

View File

@@ -0,0 +1,102 @@
{
config,
lib,
pkgs,
self,
...
}: let
unit = "authentik";
cfg = config.server.${unit};
srv = config.server;
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
};
url = lib.mkOption {
type = lib.types.str;
default = "auth.${srv.domain}";
};
homepage.name = lib.mkOption {
type = lib.types.str;
default = "Authentik";
};
homepage.description = lib.mkOption {
type = lib.types.str;
default = "Open Source Identity and Access Management";
};
homepage.icon = lib.mkOption {
type = lib.types.str;
default = "authentik.svg";
};
homepage.category = lib.mkOption {
type = lib.types.str;
default = "Services";
};
};
config = lib.mkIf cfg.enable {
age.secrets.authentikEnv = {
file = "${self}/secrets/authentikEnv.age";
owner = "authentik";
};
services = {
authentik = {
enable = true;
environmentFile = config.age.secrets.authentikEnv.path;
settings = {
email = {
};
disable_startup_analytics = true;
avatars = "initials";
};
};
traefik = {
dynamicConfigOptions = {
http = {
middlewares = {
authentik = {
forwardAuth = {
tls.insecureSkipVerify = true;
address = "https://localhost:9443/outpost.goauthentik.io/auth/traefik";
trustForwardHeader = true;
authResponseHeaders = [
"X-authentik-username"
"X-authentik-groups"
"X-authentik-email"
"X-authentik-name"
"X-authentik-uid"
"X-authentik-jwt"
"X-authentik-meta-jwks"
"X-authentik-meta-outpost"
"X-authentik-meta-provider"
"X-authentik-meta-app"
"X-authentik-meta-version"
];
};
};
};
services = {
auth.loadBalancer.servers = [
{
url = "http://localhost:9000";
}
];
};
routers = {
auth = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`) || HostRegexp(`{subdomain:[a-z0-9]+}.${srv.domain}`) && PathPrefix(`/outpost.goauthentik.io/`)";
service = "auth";
tls.certResolver = "letsencrypt";
};
};
};
};
};
};
};
}

View File

@@ -2,13 +2,11 @@
config,
lib,
...
}:
let
}: let
unit = "bazarr";
srv = config.server;
cfg = config.server.${unit};
in
{
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
@@ -44,11 +42,21 @@ in
user = srv.user;
group = srv.group;
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:${toString config.services.${unit}.listenPort}
'';
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

@@ -27,13 +27,6 @@ in {
Domain name to be used to access the server services via Caddy reverse proxy
'';
};
domainPublic = mkOption {
default = "";
type = types.str;
description = ''
Public domain name to be used to access the server services via Caddy reverse proxy
'';
};
user = lib.mkOption {
default = "share";
type = lib.types.str;
@@ -99,6 +92,8 @@ in {
"share"
"render"
"input"
"authentik"
"traefik"
];
};
};

View File

@@ -3,13 +3,11 @@
config,
lib,
...
}:
let
}: let
unit = "gitea";
srv = config.server;
cfg = config.server.${unit};
in
{
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
@@ -101,11 +99,21 @@ in
};
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:5003
'';
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 = [

View File

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

View File

@@ -2,19 +2,17 @@
config,
lib,
...
}:
let
}: let
unit = "homepage-dashboard";
cfg = config.server.homepage-dashboard;
srv = config.server;
in
{
in {
options.server.homepage-dashboard = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
};
misc = lib.mkOption {
default = [ ];
default = [];
type = lib.types.listOf (
lib.types.attrsOf (
lib.types.submodule {
@@ -38,81 +36,81 @@ in
};
};
config = lib.mkIf cfg.enable {
services.glances.enable = true;
services.${unit} = {
enable = true;
allowedHosts = srv.domain;
settings = {
layout = [
services = {
glances.enable = true;
${unit} = {
enable = true;
allowedHosts = srv.domain;
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 = [
{
Glances = {
header = false;
style = "row";
columns = 4;
openmeteo = {
label = "Kalmar";
timezone = "Europe/Stockholm";
units = "metric";
cache = 5;
latitude = 56.707262;
longitude = 16.324541;
};
}
{
Arr = {
header = true;
style = "column";
datetime = {
text_size = "x1";
format = {
hour12 = false;
timeStyle = "short";
dateStyle = "long";
};
};
}
{
Downloads = {
header = true;
style = "column";
};
}
{
Media = {
header = true;
style = "column";
};
}
{
Services = {
header = true;
style = "column";
resources = {
label = "";
memory = true;
disk = ["/"];
};
}
];
headerStyle = "clean";
statusStyle = "dot";
hideVersion = "true";
};
widgets = [
{
openmeteo = {
label = "Kalmar";
timezone = "Europe/Stockholm";
units = "metric";
cache = 5;
latitude = 56.707262;
longitude = 16.324541;
};
}
{
datetime = {
text_size = "x1";
format = {
hour12 = false;
timeStyle = "short";
dateStyle = "long";
};
};
}
{
resources = {
label = "";
memory = true;
disk = [ "/" ];
};
}
];
services =
let
services = let
homepageCategories = [
"Arr"
"Media"
@@ -122,15 +120,14 @@ in
];
hl = config.server;
mergedServices = hl // hl.podman;
homepageServices =
x:
(lib.attrsets.filterAttrs (
homepageServices = x: (lib.attrsets.filterAttrs (
name: value: value ? homepage && value.homepage.category == x
) mergedServices);
)
mergedServices);
in
lib.lists.forEach homepageCategories (cat: {
"${cat}" =
lib.lists.forEach
lib.lists.forEach homepageCategories (cat: {
"${cat}" =
lib.lists.forEach
(lib.attrsets.mapAttrsToList (name: value: {
inherit name;
url = value.url;
@@ -144,15 +141,13 @@ in
siteMonitor = "https://${x.url}${x.homepage.path or ""}";
};
});
})
++ [ { Misc = cfg.misc; } ]
++ [
{
Glances =
let
})
++ [{Misc = cfg.misc;}]
++ [
{
Glances = let
port = toString config.services.glances.port;
in
[
in [
{
Info = {
widget = {
@@ -220,14 +215,26 @@ in
};
}
];
}
];
};
services.caddy.virtualHosts."${srv.domain}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:${toString config.services.${unit}.listenPort}
'';
}
];
};
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

@@ -3,13 +3,11 @@
lib,
pkgs,
...
}:
let
}: let
service = "jellyfin";
cfg = config.server.${service};
srv = config.server;
in
{
in {
options.server.${service} = {
enable = lib.mkEnableOption {
description = "Enable ${service}";
@@ -48,11 +46,21 @@ in
environment.systemPackages = with pkgs; [
jellyfin-ffmpeg
];
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:8096
'';
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

@@ -2,13 +2,11 @@
config,
lib,
...
}:
let
}: let
service = "jellyseerr";
srv = config.server;
cfg = config.server.${service};
in
{
in {
options.server.${service} = {
enable = lib.mkEnableOption {
description = "Enable ${service}";
@@ -43,11 +41,21 @@ in
enable = true;
port = cfg.port;
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:${toString 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

@@ -1,100 +0,0 @@
{
config,
lib,
pkgs,
...
}: let
unit = "keycloak";
cfg = config.server.${unit};
srv = config.server;
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
};
url = lib.mkOption {
type = lib.types.str;
default = "login.${srv.domain}";
};
homepage.name = lib.mkOption {
type = lib.types.str;
default = "Keycloak";
};
homepage.description = lib.mkOption {
type = lib.types.str;
default = "Open Source Identity and Access Management";
};
homepage.icon = lib.mkOption {
type = lib.types.str;
default = "keycloak.svg";
};
homepage.category = lib.mkOption {
type = lib.types.str;
default = "Services";
};
dbPasswordFile = lib.mkOption {
type = lib.types.path;
};
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 = lib.mkIf cfg.enable {
server.postgresql.databases = [
{
database = "keycloak";
}
];
services.cloudflared = {
enable = true;
tunnels.${cfg.cloudflared.tunnelId} = {
credentialsFile = cfg.cloudflared.credentialsFile;
default = "http_status:404";
ingress."${cfg.url}".service = "http://127.0.0.1:${
toString config.services.${unit}.settings.http-port
}";
};
};
environment.systemPackages = [
pkgs.keycloak
];
services.${unit} = {
enable = true;
initialAdminPassword = "pwpwpw";
database = {
type = "postgresql";
host = "127.0.0.1";
port = 5432;
name = "keycloak";
username = "keycloak";
passwordFile = cfg.dbPasswordFile;
useSSL = false;
};
settings = {
spi-theme-static-max-age = "-1";
spi-theme-cache-themes = false;
spi-theme-cache-templates = false;
http-port = 8821;
hostname = cfg.url;
hostname-strict = false;
hostname-strict-https = false;
proxy-headers = "xforwarded";
http-enabled = true;
};
};
};
}

View File

@@ -2,13 +2,11 @@
config,
lib,
...
}:
let
}: let
unit = "lidarr";
srv = config.server;
cfg = config.server.${unit};
in
{
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
@@ -44,11 +42,21 @@ in
user = srv.user;
group = srv.group;
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:8686
'';
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

@@ -54,118 +54,80 @@ in {
};
};
services.${unit} = {
enable = true;
package = pkgs.nextcloud31;
hostName = "nextcloud";
configureRedis = true;
caching = {
redis = true;
};
phpOptions = {
"opcache.interned_strings_buffer" = "32";
};
maxUploadSize = "50G";
settings = {
maintenance_window_start = "1";
trusted_proxies = [
"127.0.0.1"
"::1"
];
trusted_domains = ["cloud.${srv.domain}"];
overwriteprotocol = "https";
enabledPreviewProviders = [
"OC\\Preview\\BMP"
"OC\\Preview\\GIF"
"OC\\Preview\\JPEG"
"OC\\Preview\\Krita"
"OC\\Preview\\MarkDown"
"OC\\Preview\\MP3"
"OC\\Preview\\OpenDocument"
"OC\\Preview\\PNG"
"OC\\Preview\\TXT"
"OC\\Preview\\XBitmap"
"OC\\Preview\\HEIC"
];
};
config = {
dbtype = "pgsql";
dbuser = "nextcloud";
dbhost = "/run/postgresql";
dbname = "nextcloud";
adminuser = "cnst";
adminpassFile = cfg.adminpassFile;
};
};
users.groups.nextcloud.members = [
config.services.caddy.user
];
services = {
nginx.enable = false;
phpfpm.pools.nextcloud.settings = {
"listen.owner" = config.services.caddy.user;
"listen.group" = config.services.caddy.group;
${unit} = {
enable = true;
package = pkgs.nextcloud31;
hostName = "nextcloud";
configureRedis = true;
caching = {
redis = true;
};
phpOptions = {
"opcache.interned_strings_buffer" = "32";
};
maxUploadSize = "50G";
settings = {
maintenance_window_start = "1";
trusted_proxies = [
"127.0.0.1"
"::1"
];
trusted_domains = ["cloud.${srv.domain}"];
overwriteprotocol = "https";
enabledPreviewProviders = [
"OC\\Preview\\BMP"
"OC\\Preview\\GIF"
"OC\\Preview\\JPEG"
"OC\\Preview\\Krita"
"OC\\Preview\\MarkDown"
"OC\\Preview\\MP3"
"OC\\Preview\\OpenDocument"
"OC\\Preview\\PNG"
"OC\\Preview\\TXT"
"OC\\Preview\\XBitmap"
"OC\\Preview\\HEIC"
];
};
config = {
dbtype = "pgsql";
dbuser = "nextcloud";
dbhost = "/run/postgresql";
dbname = "nextcloud";
adminuser = "cnst";
adminpassFile = cfg.adminpassFile;
};
};
caddy.virtualHosts.${cfg.url} = let
webroot = config.services.nginx.virtualHosts.nextcloud.root;
in {
useACMEHost = srv.domain;
extraConfig = ''
encode zstd gzip
root * ${webroot}
redir /.well-known/carddav /remote.php/dav 301
redir /.well-known/caldav /remote.php/dav 301
redir /.well-known/* /index.php{uri} 301
redir /remote/* /remote.php{uri} 301
header {
Strict-Transport-Security max-age=31536000
Permissions-Policy interest-cohort=()
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy no-referrer
X-XSS-Protection "1; mode=block"
X-Permitted-Cross-Domain-Policies none
X-Robots-Tag "noindex, nofollow"
-X-Powered-By
}
php_fastcgi unix/${config.services.phpfpm.pools.nextcloud.socket} {
root ${webroot}
env front_controller_active true
env modHeadersAvailable true
}
@forbidden {
path /build/* /tests/* /config/* /lib/* /3rdparty/* /templates/* /data/*
path /.* /autotest* /occ* /issue* /indie* /db_* /console*
not path /.well-known/*
}
error @forbidden 404
@immutable {
path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite
query v=*
}
header @immutable Cache-Control "max-age=15778463, immutable"
@static {
path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite
not query v=*
nginx = {
defaultListen = [
{
addr = "127.0.0.1";
port = 8182;
}
header @static Cache-Control "max-age=15778463"
{
addr = "127.0.0.1";
port = 8482;
}
];
virtualHosts.nextcloud = {
forceSSL = false;
};
};
@woff2 path *.woff2
header @woff2 Cache-Control "max-age=604800"
file_server
'';
traefik.dynamicConfigOptions.http = {
routers.nextcloud = {
entryPoints = ["websecure"];
rule = "Host(`${cfg.url}`)";
service = "nextcloud";
tls.certResolver = "letsencrypt";
};
services.nextcloud.loadBalancer.servers = [
{url = "http://127.0.0.1:8182";}
];
};
};
server.postgresql.databases = [
{
database = "nextcloud";

View File

@@ -137,31 +137,58 @@ in {
];
};
services.caddy.virtualHosts = lib.mkMerge [
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 {
"${cfg.qbittorrent.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:${toString cfg.qbittorrent.port}
'';
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 {
"${cfg.slskd.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:${toString cfg.slskd.port}
'';
};
})
(lib.mkIf cfg.pihole.enable {
"${cfg.pihole.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:${toString cfg.pihole.port}
'';
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";
};
};
};
};
})
];
@@ -268,9 +295,6 @@ in {
environment = {
TZ = "Europe/Stockholm";
CUSTOM_CACHE_SIZE = "0";
# PIHOLE_DNS_ = "10.88.0.1#5335";
# DNSSEC = "false";
# REV_SERVER = "true";
WEBTHEME = "default-darker";
};
environmentFiles = getPiholeSecret config.networking.hostName;

View File

@@ -2,13 +2,11 @@
config,
lib,
...
}:
let
}: let
unit = "prowlarr";
srv = config.server;
cfg = config.server.${unit};
in
{
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
@@ -47,18 +45,34 @@ in
enable = true;
};
caddy = {
virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:9696
'';
};
virtualHosts."flaresolverr.${srv.domain}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:8191
'';
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

@@ -2,13 +2,11 @@
config,
lib,
...
}:
let
}: let
unit = "radarr";
srv = config.server;
cfg = config.server.${unit};
in
{
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
@@ -44,11 +42,21 @@ in
user = srv.user;
group = srv.group;
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:7878
'';
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

@@ -2,13 +2,11 @@
config,
lib,
...
}:
let
}: let
unit = "sonarr";
srv = config.server;
cfg = config.server.${unit};
in
{
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
@@ -44,11 +42,21 @@ in
user = srv.user;
group = srv.group;
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:8989
'';
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

@@ -1,62 +0,0 @@
{
config,
lib,
...
}: let
unit = "syncthing";
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 = "${unit}.${srv.domain}";
};
homepage.name = lib.mkOption {
type = lib.types.str;
default = "Syncthing";
};
homepage.description = lib.mkOption {
type = lib.types.str;
default = "Continuous file synchronization program";
};
homepage.icon = lib.mkOption {
type = lib.types.str;
default = "syncthing.svg";
};
homepage.category = lib.mkOption {
type = lib.types.str;
default = "Services";
};
};
config = lib.mkIf cfg.enable {
networking.firewall = {
allowedTCPPorts = [
8384
22000
];
allowedUDPPorts = [
22000
21027
];
};
services.${unit} = {
enable = true;
user = srv.user;
guiAddress = "0.0.0.0:8384";
overrideFolders = false;
overrideDevices = false;
dataDir = "/home/${srv.user}/syncthing";
configDir = "/home/${srv.user}/syncthing/.config/syncthing";
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:8384
'';
};
};
}

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

@@ -2,13 +2,11 @@
config,
lib,
...
}:
let
}: let
unit = "uptime-kuma";
cfg = config.server.${unit};
srv = config.server;
in
{
in {
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
@@ -39,14 +37,26 @@ in
};
};
config = lib.mkIf cfg.enable {
services.${unit} = {
enable = true;
};
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = srv.domain;
extraConfig = ''
reverse_proxy http://127.0.0.1:3001
'';
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,44 @@
{
lib,
config,
pkgs,
...
}: let
inherit (lib) mkOption mkEnableOption mkIf types;
cfg = config.server.www;
srv = config.server;
in {
options.server.www = {
enable = mkEnableOption {
description = "Enable personal website";
};
url = mkOption {
default = "";
type = types.str;
description = ''
Public domain name to be used to access the server services via Caddy reverse proxy
'';
};
};
config = mkIf cfg.enable {
services.caddy.virtualHosts."${cfg.url}" = {
useACMEHost = cfg.url;
extraConfig = ''
handle_path /.well-known/webfinger {
header Content-Type application/jrd+json
respond `{
"subject": "acct:adam@${cfg.url}",
"links": [
{
"rel": "http://openid.net/specs/connect/1.0/issuer",
"href": "https://login.${cfg.url}/realms/cnix"
}
]
}`
}
reverse_proxy http://127.0.0.1:8283
'';
};
};
}

View File

@@ -1,77 +0,0 @@
# Ghostty spawn-or-focus logic for Niri:
# If no Ghostty windows exist, spawn one.
# If focused window is not Ghostty, focus the first Ghostty instance.
# If Ghostty is focused and only one instance exists, spawn + consume into stack.
# If Ghostty is focused and two instances already exist, spawn a new separate one.
# Cycle repeats: focus first > allow stack of 2 > reset on 3rd.
APP_ID="com.mitchellh.ghostty"
APP_CMD="ghostty"
WINDOW_DATA=$(niri msg -j windows)
readarray -t GHOSTTY_IDS < <(
echo "$WINDOW_DATA" | jq -r --arg app_id "$APP_ID" '
[ .[] | select(.app_id == $app_id) ]
| sort_by(.layout.pos_in_scrolling_layout // [0,0])
| .[].id
'
)
COUNT=${#GHOSTTY_IDS[@]}
FOCUSED_IS_GHOSTTY=$(
echo "$WINDOW_DATA" | jq -r --arg app_id "$APP_ID" '
any(.[]; .app_id == $app_id and .is_focused)
'
)
spawn_normal() {
"$APP_CMD" &
}
spawn_and_consume() {
local initial_ids=("$@")
"$APP_CMD" &
local pid=$!
for _ in {1..50}; do
readarray -t after_ids < <(
niri msg -j windows | jq -r --arg app_id "$APP_ID" '
[ .[] | select(.app_id == $app_id) ]
| sort_by(.layout.pos_in_scrolling_layout // [0,0])
| .[].id
'
)
NEW_ID=""
for id in "${after_ids[@]}"; do
[[ " ${initial_ids[*]} " == *" $id "* ]] || NEW_ID="$id"
done
if [ -n "$NEW_ID" ]; then
niri msg action focus-window --id "${initial_ids[$((${#initial_ids[@]} - 1))]}"
niri msg action consume-window-into-column
break
fi
sleep 0.05
done
wait "$pid" 2>/dev/null || true
}
if ((COUNT == 0)); then
spawn_normal
exit 0
fi
if [ "$FOCUSED_IS_GHOSTTY" != "true" ]; then
niri msg action focus-window --id "${GHOSTTY_IDS[0]}"
exit 0
fi
if ((COUNT % 2 == 0)); then
spawn_normal
else
spawn_and_consume "${GHOSTTY_IDS[@]}"
fi

BIN
secrets/authentikEnv.age Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -1,11 +1,11 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg QY+660BNebZu+onRxjUCOqQ4iqCySPWfw9eCLXdFsl8
AP1XZcDAY4/hrtyTnVXEpybPgEh38PcMaiiBPTlkDZ8
-> ssh-ed25519 KUYMFA nCLslugBChJUP4e6XXxV5GGUZdM/YHcOqSQEzgBnpnk
9Y/N0Clq/qSGa/XHGKr5Yg6iz40fb+5Rti+6RvEoiXs
-> ssh-ed25519 76RhUQ ZeJds5ce27IAjkBpECnQY73Y0g2eB8lI5g2K3wn3STQ
IQ8TZ/jrTme1cUxzSDNYN6hfHKXJV9aKNXFP7jNWlgs
-> ssh-ed25519 Jf8sqw 6o1aN6NB+YgDM/q1DyTwRGbE85oOvyyGGNGIrd+P31Q
QpL1gGnfLs2Xm7Sx0jVE3Cx4J7aIzcUOXUp9Yt/Ztt0
--- DR/KkJALCKIdMQvWi1abl8Q9UWJVPSv/a3sAoxY/t2Q
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>gPm<EFBFBD>?\<5C><><EFBFBD>}v/[
-> ssh-ed25519 t9iOEg EO9wY72yR1e+1vy7G+bSpm2Rcv6bv/Df0D1i/SO+zA0
pmABveIZ53zQOoJ27P4zqb0jtaDJoYkhclMP6wcl+ZM
-> ssh-ed25519 KUYMFA h02lppvPUe8eJLAfIEkGQqgdNWqvFYpJ2eZjJGHJ+SA
5+T4ytKUXPdIIDXfcc/LUnQsOMlmck2Ug32MKNuCh2Q
-> ssh-ed25519 76RhUQ E/ng+K+F+iaNZ0QjSyo2JuAz717aoygNguzon798dlI
CPJV+mjKX1ZtmWvBroFHVyuRnnUI5ymfEw6OqnQa2kI
-> ssh-ed25519 Jf8sqw yrWSLSAjsIfyd+DYUyojy0k6GwMa3ZmVjyIz36gLin0
ly8wMETBPdaF5dM5r//UCdfSqTMEfnodffgIAUGydcE
--- kNDVEUJATIeuOYNXY/Bl++PfDEn/lCo4nBiTEFntOw0
<EFBFBD>g<EFBFBD><EFBFBD>Q=[g<><16>?_<><5F>|<7C><>7[<5B><>-<2D><>CngڡǗ<01>+<2B>m<><6D><r<01><>bv?i<><69>S<EFBFBD>2W<32>f<EFBFBD><66>51<11><>P<>x~<13><>_c<5F>"m<><01>)<29><>h"I<>

Binary file not shown.

View File

@@ -1,11 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg JGPsdwpo+QYwoEtQp5O7esvdpxDmBtSaAFa42xUrziA
O/fLTeyC+01JM0Iqc3PfW0LTEW1CTSCXvnzcTpGhiZs
-> ssh-ed25519 KUYMFA ELcXHREdinnJGyLmGP52mCe6wT6FPBAh6STAmphI1gM
UEAyd9Pl4GqxfgRvX4TkNjX+iCoPbIaBe4jZRgfxtKM
-> ssh-ed25519 76RhUQ iLb/XlmQRU7NBJ0qACMWzdcekWLJdewuY8XK88QMgho
cwydjm9RJ3Oj36OhBCCpdN1nIZICqpVcm/Icl+1buC8
-> ssh-ed25519 Jf8sqw /VcINacatv58hd3KxVjVWm6Jg6ZZszbrA7xMuScfMwE
e5GHPaF3oXfmRKrcII3w48XH+nvvEJGdORUnfJR/jE0
--- HxSA44rqWWFjoHeJaGi7VCsPdmksyMCytkv75TaTGfU
<EFBFBD><EFBFBD><EFBFBD>Muމ<EFBFBD><<3C>(<28>~82<38><32>a<><1A><><EFBFBD>pfI<66>I<EFBFBD><49>^L<>%<25>2㛔<32>b<EFBFBD>q<EFBFBD><71><EFBFBD><EFBFBD>/As:B<>]<5D>]<5D>Ż<EFBFBD>

View File

@@ -40,8 +40,6 @@ in {
"homepageEnvironment.age".publicKeys = core ++ sobotka;
"cloudflareFirewallApiKey.age".publicKeys = core ++ sobotka;
"vaultwardenCloudflared.age".publicKeys = core ++ sobotka;
"keycloakDbPasswordFile.age".publicKeys = core ++ sobotka;
"keycloakCloudflared.age".publicKeys = core ++ sobotka;
"nextcloudCloudflared.age".publicKeys = core ++ sobotka;
"nextcloudAdminPass.age".publicKeys = core ++ sobotka;
"cloudflareDnsApiToken.age".publicKeys = core ++ sobotka;
@@ -51,6 +49,8 @@ in {
"gluetunEnvironment.age".publicKeys = core ++ sobotka;
"pihole.age".publicKeys = core ++ sobotka;
"slskd.age".publicKeys = core ++ sobotka;
"authentikEnv.age".publicKeys = core ++ sobotka;
"traefikEnv.age".publicKeys = core ++ sobotka;
# Ziggy-specific
"cloudflareDnsCredentialsZiggy.age".publicKeys = core ++ ziggy;

BIN
secrets/sslCert.age Normal file

Binary file not shown.

BIN
secrets/sslKey.age Normal file

Binary file not shown.

BIN
secrets/traefikEnv.age Normal file

Binary file not shown.