From 80d0f8fc9fb158217e6e75b4a71d1987ea9b5a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Sun, 19 Oct 2025 03:19:30 +0800 Subject: [PATCH 1/4] WIP: Auth --- configuration/default.nix | 1 + configuration/services/auth/authelia.nix | 87 ++++++++++++++++++++++++ configuration/services/auth/default.nix | 5 ++ configuration/services/postgres.nix | 5 ++ keys/staging.yaml | 10 ++- 5 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 configuration/services/auth/authelia.nix create mode 100644 configuration/services/auth/default.nix diff --git a/configuration/default.nix b/configuration/default.nix index f2d1615..041c885 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -13,6 +13,7 @@ "${modulesPath}/profiles/minimal.nix" (import ../modules) + ./services/auth ./services/backups.nix ./services/battery-manager.nix ./services/conduit diff --git a/configuration/services/auth/authelia.nix b/configuration/services/auth/authelia.nix new file mode 100644 index 0000000..f05e3f0 --- /dev/null +++ b/configuration/services/auth/authelia.nix @@ -0,0 +1,87 @@ +{ config, ... }: +let + instanceName = config.services.authelia.instances.main.name; +in +{ + services.authelia.instances.main = { + enable = true; + + settings = { + theme = "auto"; + default_2fa_method = "totp"; + + authentication_backend = { + password_reset.disable = true; + password_change.disable = true; + + file = { + inherit (config.sops.secrets."authelia/users") path; + + search = { + email = true; + case_insensitive = false; + }; + }; + }; + + storage.postgres = { + address = "unix:///run/postgresql"; + database = "authelia"; + username = "authelia"; + }; + + session.cookies = [ + { + domain = config.services.nginx.domain; + authelia_url = "https://auth.${config.services.nginx.domain}"; + } + ]; + + notifier.filesystem.filename = ''{{ env "RUNTIME_DIRECTORY" }}/authelia-notifications''; + + access_control = { + + }; + + server = { + # Maybe a systemd socket can be used for this in the future, + # see: + # https://github.com/systemd/systemd/issues/23067#issuecomment-1212232155 + address = "unix://${config.systemd.sockets."authelia-${instanceName}".socketConfig.ListenStream}"; + }; + }; + + secrets = { + jwtSecretFile = config.sops.secrets."authelia/jwt".path; + storageEncryptionKeyFile = config.sops.secrets."authelia/storage".path; + }; + }; + + systemd.sockets."authelia-${instanceName}" = { + socketConfig = { + Accept = false; + ListenStream = "/var/run/authelia.sock"; + SocketGroup = "authelia"; + SocketMode = "0660"; + }; + }; + + systemd.services."authelia-${instanceName}" = { + requires = [ "authelia-${instanceName}.socket" ]; + + serviceConfig = { + RuntimeDirectory = "authelia-${instanceName}"; + SupplementaryGroups = [ "authelia" ]; + }; + }; + + # TODO: Need to map these to systemd creds to pass them into the + # service because user permissions + sops.secrets = { + "authelia/users" = { }; + "authelia/jwt" = { }; + "authelia/storage" = { }; + }; + + users.groups.authelia = { }; +} diff --git a/configuration/services/auth/default.nix b/configuration/services/auth/default.nix new file mode 100644 index 0000000..4b9c671 --- /dev/null +++ b/configuration/services/auth/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./authelia.nix + ]; +} diff --git a/configuration/services/postgres.nix b/configuration/services/postgres.nix index 85a6843..ddb2c82 100644 --- a/configuration/services/postgres.nix +++ b/configuration/services/postgres.nix @@ -17,6 +17,10 @@ # that operation needs to be performed manually on the system as # well. ensureUsers = [ + { + name = "authelia"; + ensureDBOwnership = true; + } { name = "grafana"; ensureDBOwnership = true; @@ -28,6 +32,7 @@ ]; ensureDatabases = [ + "authelia" "grafana" "nextcloud" ]; diff --git a/keys/staging.yaml b/keys/staging.yaml index 6fa212d..caa5707 100644 --- a/keys/staging.yaml +++ b/keys/staging.yaml @@ -1,3 +1,7 @@ +authelia: + users: "" + jwt: ENC[AES256_GCM,data:oKA1B7zZAzTZL4nBdHvPENVx7M2BgbMBmNtetri0qCVB7qNFIgbnwVCJFiDvjKxxNdedqUKBZZL5QJbTlPNRxCVdFgBBMFiib3khxMP8kzqff2MgJZxumonlJt5Jmh8tVxwLRJwE/2fp/N9w2hRs0vhfmMyAA4y7RZv3R9/eaKM=,iv:2iTAwP6dipPBMskyygnBJHJ53E0nmHYcGyWDrODEs1Q=,tag:koSEZtQQzOzpbQBgUP5ZHw==,type:str] + storage: ENC[AES256_GCM,data:bO+bHu6jRvfbLU6xIDaE2JwXpNnMK916Upv43ycg9fCb+U5hqQfqBBwC2xVEVXtCBRq1VER+gc8rs8/XDT9vZkvMUqAHj4RqXHyzX0UjwsvccBJSLfoLUiT6obk3oVLo5CY7R2TukPuyFXPbMUOrBk9gnbk7z4IWzcwNnuOKBT4=,iv:RmKIS/cgZ0tUQDFF2yfaJnfTvPaeadjG0LPXKIzYFrA=,tag:XmqDhDf3Ja1BsyrYmzTKDg==,type:str] porkbun: api-key: ENC[AES256_GCM,data:A5J1sqwq6hs=,iv:77Mar3IX7mq7z7x6s9sSeGNVYc1Wv78HptJElEC7z3Q=,tag:eM/EF9TxKu+zcbJ1SYXiuA==,type:str] secret-api-key: ENC[AES256_GCM,data:8Xv+jWYaWMI=,iv:li4tdY0pch5lksftMmfMVS729caAwfaacoztaQ49az0=,tag:KhfElBGzVH4ByFPfuQsdhw==,type:str] @@ -32,8 +36,8 @@ turn: #ENC[AES256_GCM,data:bxhKzU5Tzezl749CDu8e8kxa7ahGuZFaPa9K3kxuD+4sg5Hi3apgDlC0n8oK0DeiK4Ks7+9Cyw==,iv:T/zVJUpNAv1rR0a9+6SDTG08ws2A1hFBs5Ia3TpT0uk=,tag:uGXb1VryM+lIJ8r0I5durA==,type:comment] ssl-cert: ENC[AES256_GCM,data:xHUr14CjKslgbGh/n5jYSOuCw9JRxS6YXE4fxS+aJzFcNeSeGNqoipPeuJupZGBnQP/FCqohiHY=,iv:/OEsVqRshGL9NIvntMC42EPZSNL0u6EfhtUBqgV7qog=,tag:4pxtNjuvy/ibm6nDtKdSkw==,type:str] sops: - lastmodified: "2025-02-07T17:43:24Z" - mac: ENC[AES256_GCM,data:akmD/bfgeTyFzW1quvM16cdj0fC6+CbJ8WyX9173H11yKGxvE1USQYcErpl1SHOx9Jk8LVb7f+MsUm2fjQF1MEq6xaWI74jem12lZ9CGXFaTL7e87JvfbK7pV+aKpxSBBNFyJgbYm30ibdUwxwKmNVfPb1e0HT9qwenvoV7RobM=,iv:mKqOW0ULXL711uczUbRf9NPo6uPTQoS/IbR46S+JID4=,tag:vE6NYzYLbQHDImov1XGTcg==,type:str] + lastmodified: "2025-10-20T20:04:21Z" + mac: ENC[AES256_GCM,data:kRrmVm3PQooRA/MoHgDb9EaRnoKY9CJxAflus9Po8NBmyQxV6Ehjf8DlI6yf7ZpPlhV+VHZJamyPD+hsHp1hSr8krvr0o52ZQdKn4MJQzSQXa4K9i3i0+glj7cNGs2SzTJnKwN9lxBywZpbVDlkXmvRQYLE9tWPWoSBdurOibjw=,iv:2iBQ1cYT85mCc7jf2GTEOjNiHBlR/F76Dvjl/k5dyLA=,tag:Z7dY2i0KWmmoVp7VJjq1Sw==,type:str] pgp: - created_at: "2025-10-03T21:38:26Z" enc: |- @@ -67,4 +71,4 @@ sops: -----END PGP MESSAGE----- fp: 2f5caa73e7ceea4fcc8d2881fde587e6737d2dbc unencrypted_suffix: _unencrypted - version: 3.9.2 + version: 3.11.0 From 79eb8f94248a171100c8225f98a695d0dd87bcfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Nov 2025 01:29:19 +0800 Subject: [PATCH 2/4] feat(checks): Fully rework lints This is currently copied from my dotfiles. Should probably consider using flake-parts to DRY this out. --- checks/default.nix | 94 ++--- checks/lib.nix | 35 ++ flake.lock | 864 ++++++--------------------------------------- flake.nix | 48 ++- 4 files changed, 221 insertions(+), 820 deletions(-) create mode 100644 checks/lib.nix diff --git a/checks/default.nix b/checks/default.nix index f3db4ce..674b19d 100644 --- a/checks/default.nix +++ b/checks/default.nix @@ -1,61 +1,45 @@ -{ - self, - nixpkgs, - deploy-rs, - system, - ... -}: +{ flake-inputs }: let - pkgs = nixpkgs.legacyPackages.${system}; - - statix' = pkgs.statix.overrideAttrs (old: { - patches = old.patches ++ [ - (pkgs.fetchpatch { - url = "https://github.com/oppiliappan/statix/commit/925dec39bb705acbbe77178b4d658fe1b752abbb.patch"; - hash = "sha256-0wacO6wuYJ4ufN9PGucRVJucFdFFNF+NoHYIrLXsCWs="; - }) - ]; - }); - - runNuCheck = + inherit (flake-inputs.nixpkgs) lib; + pkgs = flake-inputs.nixpkgs.legacyPackages.x86_64-linux; + checkLib = pkgs.callPackage ./lib.nix { }; +in +{ + x86_64-linux = lib.mergeAttrsList [ { - name, - packages, - check, - }: - pkgs.stdenvNoCC.mkDerivation { - inherit name; + nix = checkLib.mkLint { + name = "nix-lints"; + fileset = lib.fileset.fileFilter (file: file.hasExt "nix") ../.; - src = nixpkgs.lib.cleanSourceWith { - src = self; - filter = nixpkgs.lib.cleanSourceFilter; + checkInputs = lib.attrValues { + inherit (pkgs) deadnix nixfmt-rfc-style; + + statix = pkgs.statix.overrideAttrs (old: { + patches = old.patches ++ [ + (pkgs.fetchpatch { + url = "https://github.com/oppiliappan/statix/commit/925dec39bb705acbbe77178b4d658fe1b752abbb.patch"; + hash = "sha256-0wacO6wuYJ4ufN9PGucRVJucFdFFNF+NoHYIrLXsCWs="; + }) + ]; + }); + }; + + script = '' + statix check **/*.nix + deadnix --fail **/*.nix + nixfmt --check --strict **/*.nix + ''; }; - dontPatch = true; - dontConfigure = true; - dontBuild = true; - dontInstall = true; - dontFixup = true; - doCheck = true; + lockfile = checkLib.mkLint { + name = "nix-lockfile"; + fileset = ../flake.lock; + checkInputs = lib.attrValues { inherit (flake-inputs.flint.packages.x86_64-linux) flint; }; - checkInputs = nixpkgs.lib.singleton pkgs.nushell ++ packages; - - checkPhase = '' - nu ${check} - ''; - }; -in -nixpkgs.lib.recursiveUpdate { - lints = runNuCheck { - name = "lints"; - - packages = [ - pkgs.deadnix - pkgs.nixfmt-rfc-style - pkgs.shellcheck - statix' - ]; - - check = ./lints.nu; - }; -} (deploy-rs.lib.${system}.deployChecks self.deploy) + script = '' + flint --fail-if-multiple-versions + ''; + }; + } + ]; +} diff --git a/checks/lib.nix b/checks/lib.nix new file mode 100644 index 0000000..d38cd21 --- /dev/null +++ b/checks/lib.nix @@ -0,0 +1,35 @@ +{ pkgs, lib, ... }: +{ + mkLint = + { + name, + fileset, + checkInputs ? [ ], + script, + }: + pkgs.stdenvNoCC.mkDerivation { + inherit name; + + src = lib.fileset.toSource { + root = ../.; + fileset = lib.fileset.difference fileset ( + lib.fileset.fileFilter ( + file: file.type != "regular" || file.name == "hardware-configuration.nix" + ) ../. + ); + }; + + checkInputs = [ pkgs.nushell ] ++ checkInputs; + + checkPhase = '' + nu -c '${script}' | tee $out + ''; + + dontPatch = true; + dontConfigure = true; + dontBuild = true; + dontInstall = true; + dontFixup = true; + doCheck = true; + }; +} diff --git a/flake.lock b/flake.lock index a62c357..705d87c 100644 --- a/flake.lock +++ b/flake.lock @@ -10,89 +10,17 @@ "sonnenshift", "crate2nix" ], - "nixpkgs": "nixpkgs_3", - "pre-commit-hooks": [ - "sonnenshift", - "crate2nix" + "git-hooks": "git-hooks", + "nixpkgs": [ + "nixpkgs" ] }, "locked": { - "lastModified": 1709700175, - "narHash": "sha256-A0/6ZjLmT9qdYzKHmevnEIC7G+GiZ4UCr8v0poRPzds=", + "lastModified": 1760971495, + "narHash": "sha256-IwnNtbNVrlZIHh7h4Wz6VP0Furxg9Hh0ycighvL5cZc=", "owner": "cachix", "repo": "cachix", - "rev": "be97b37989f11b724197b5f4c7ffd78f12c8c4bf", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "latest", - "repo": "cachix", - "type": "github" - } - }, - "cachix_2": { - "inputs": { - "devenv": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable" - ], - "flake-compat": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable" - ], - "nixpkgs": "nixpkgs_4", - "pre-commit-hooks": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable" - ] - }, - "locked": { - "lastModified": 1716549461, - "narHash": "sha256-lHy5kgx6J8uD+16SO47dPrbob98sh+W1tf4ceSqPVK4=", - "owner": "cachix", - "repo": "cachix", - "rev": "e2bb269fb8c0828d5d4d2d7b8d09ea85abcacbd4", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "latest", - "repo": "cachix", - "type": "github" - } - }, - "cachix_3": { - "inputs": { - "devenv": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "crate2nix_stable" - ], - "flake-compat": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "crate2nix_stable" - ], - "nixpkgs": "nixpkgs_5", - "pre-commit-hooks": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "crate2nix_stable" - ] - }, - "locked": { - "lastModified": 1716549461, - "narHash": "sha256-lHy5kgx6J8uD+16SO47dPrbob98sh+W1tf4ceSqPVK4=", - "owner": "cachix", - "repo": "cachix", - "rev": "e2bb269fb8c0828d5d4d2d7b8d09ea85abcacbd4", + "rev": "c5bfd933d1033672f51a863c47303fc0e093c2d2", "type": "github" }, "original": { @@ -105,16 +33,21 @@ "crate2nix": { "inputs": { "cachix": "cachix", - "crate2nix_stable": "crate2nix_stable", - "devshell": "devshell_3", - "flake-compat": "flake-compat_4", - "flake-parts": "flake-parts_3", - "nix-test-runner": "nix-test-runner_3", - "nixpkgs": [ + "crate2nix_stable": [ "sonnenshift", + "crate2nix" + ], + "devshell": "devshell", + "flake-compat": [ + "deploy-rs", + "flake-compat" + ], + "flake-parts": "flake-parts", + "nix-test-runner": "nix-test-runner", + "nixpkgs": [ "nixpkgs" ], - "pre-commit-hooks": "pre-commit-hooks_3" + "pre-commit-hooks": "pre-commit-hooks" }, "locked": { "lastModified": 1739473963, @@ -130,81 +63,12 @@ "type": "github" } }, - "crate2nix_stable": { - "inputs": { - "cachix": "cachix_2", - "crate2nix_stable": "crate2nix_stable_2", - "devshell": "devshell_2", - "flake-compat": "flake-compat_3", - "flake-parts": "flake-parts_2", - "nix-test-runner": "nix-test-runner_2", - "nixpkgs": "nixpkgs_7", - "pre-commit-hooks": "pre-commit-hooks_2" - }, - "locked": { - "lastModified": 1719760004, - "narHash": "sha256-esWhRnt7FhiYq0CcIxw9pvH+ybOQmWBfHYMtleaMhBE=", - "owner": "nix-community", - "repo": "crate2nix", - "rev": "1dee214bb20855fa3e1e7bb98d28922ddaff8c57", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "0.14.1", - "repo": "crate2nix", - "type": "github" - } - }, - "crate2nix_stable_2": { - "inputs": { - "cachix": "cachix_3", - "crate2nix_stable": "crate2nix_stable_3", - "devshell": "devshell", - "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts", - "nix-test-runner": "nix-test-runner", - "nixpkgs": "nixpkgs_6", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1712821484, - "narHash": "sha256-rGT3CW64cJS9nlnWPFWSc1iEa3dNZecVVuPVGzcsHe8=", - "owner": "nix-community", - "repo": "crate2nix", - "rev": "42883afcad3823fa5811e967fb7bff54bc3c9d6d", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "0.14.0", - "repo": "crate2nix", - "type": "github" - } - }, - "crate2nix_stable_3": { - "inputs": { - "flake-utils": "flake-utils" - }, - "locked": { - "lastModified": 1702842982, - "narHash": "sha256-A9AowkHIjsy1a4LuiPiVP88FMxyCWK41flZEZOUuwQM=", - "owner": "nix-community", - "repo": "crate2nix", - "rev": "75ac2973affa6b9b4f661a7b592cba6e4f51d426", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "0.12.0", - "repo": "crate2nix", - "type": "github" - } - }, "deploy-rs": { "inputs": { "flake-compat": "flake-compat", - "nixpkgs": "nixpkgs", + "nixpkgs": [ + "nixpkgs" + ], "utils": "utils" }, "locked": { @@ -223,56 +87,6 @@ }, "devshell": { "inputs": { - "flake-utils": "flake-utils_2", - "nixpkgs": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1717408969, - "narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=", - "owner": "numtide", - "repo": "devshell", - "rev": "1ebbe68d57457c8cae98145410b164b5477761f4", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, - "devshell_2": { - "inputs": { - "flake-utils": "flake-utils_3", - "nixpkgs": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1717408969, - "narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=", - "owner": "numtide", - "repo": "devshell", - "rev": "1ebbe68d57457c8cae98145410b164b5477761f4", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, - "devshell_3": { - "inputs": { - "flake-utils": "flake-utils_4", "nixpkgs": [ "sonnenshift", "crate2nix", @@ -280,11 +94,11 @@ ] }, "locked": { - "lastModified": 1711099426, - "narHash": "sha256-HzpgM/wc3aqpnHJJ2oDqPBkNsqWbW0WfWUO8lKu8nGk=", + "lastModified": 1762521437, + "narHash": "sha256-RXN+lcx4DEn3ZS+LqEJSUu/HH+dwGvy0syN7hTo/Chg=", "owner": "numtide", "repo": "devshell", - "rev": "2d45b54ca4a183f2fdcf4b19c895b64fbf620ee8", + "rev": "07bacc9531f5f4df6657c0a02a806443685f384a", "type": "github" }, "original": { @@ -315,16 +129,18 @@ }, "dream2nix": { "inputs": { - "nixpkgs": "nixpkgs_8", + "nixpkgs": [ + "nixpkgs" + ], "purescript-overlay": "purescript-overlay", "pyproject-nix": "pyproject-nix" }, "locked": { - "lastModified": 1735160684, - "narHash": "sha256-n5CwhmqKxifuD4Sq4WuRP/h5LO6f23cGnSAuJemnd/4=", + "lastModified": 1754978539, + "narHash": "sha256-nrDovydywSKRbWim9Ynmgj8SBm8LK3DI2WuhIqzOHYI=", "owner": "nix-community", "repo": "dream2nix", - "rev": "8ce6284ff58208ed8961681276f82c2f8f978ef4", + "rev": "fbec3263cb4895ac86ee9506cdc4e6919a1a2214", "type": "github" }, "original": { @@ -371,112 +187,7 @@ "type": "github" } }, - "flake-compat_2": { - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "revCount": 57, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" - } - }, - "flake-compat_3": { - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "revCount": 57, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" - } - }, - "flake-compat_4": { - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "revCount": 57, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" - } - }, - "flake-compat_5": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1719745305, - "narHash": "sha256-xwgjVUpqSviudEkpQnioeez1Uo2wzrsMaJKJClh+Bls=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "c3c5ecc05edc7dafba779c6c1a61cd08ac6583e9", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-parts_2": { - "inputs": { - "nixpkgs-lib": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1719745305, - "narHash": "sha256-xwgjVUpqSviudEkpQnioeez1Uo2wzrsMaJKJClh+Bls=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "c3c5ecc05edc7dafba779c6c1a61cd08ac6583e9", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-parts_3": { "inputs": { "nixpkgs-lib": [ "sonnenshift", @@ -498,93 +209,23 @@ "type": "github" } }, - "flake-utils": { + "flint": { "inputs": { - "systems": "systems_2" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "lastModified": 1762437643, + "narHash": "sha256-nQ2ItqrkvOYEjJr1HcXkIEFS4SEy5q1ax0Y1CTuKhHs=", + "owner": "NotAShelf", + "repo": "flint", + "rev": "36c565edd971166718d21ae973c792b194ca737d", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "inputs": { - "systems": "systems_3" - }, - "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_3": { - "inputs": { - "systems": "systems_4" - }, - "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_4": { - "inputs": { - "systems": "systems_5" - }, - "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_5": { - "inputs": { - "systems": "systems_6" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "NotAShelf", + "repo": "flint", "type": "github" } }, @@ -608,61 +249,43 @@ "type": "github" } }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "sonnenshift", + "crate2nix", + "cachix", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "sonnenshift", + "crate2nix", + "cachix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762868777, + "narHash": "sha256-QqS72GvguP56oKDNUckWUPNJHjsdeuXh5RyoKz0wJ+E=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "c5c3147730384576196fb5da048a6e45dee10d56", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ "sonnenshift", "crate2nix", - "crate2nix_stable", - "crate2nix_stable", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "gitignore_2": { - "inputs": { - "nixpkgs": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "gitignore_3": { - "inputs": { - "nixpkgs": [ - "sonnenshift", - "crate2nix", - "pre-commit-hooks", + "cachix", + "git-hooks", "nixpkgs" ] }, @@ -696,55 +319,7 @@ "type": "github" } }, - "nix-test-runner_2": { - "flake": false, - "locked": { - "lastModified": 1588761593, - "narHash": "sha256-FKJykltAN/g3eIceJl4SfDnnyuH2jHImhMrXS2KvGIs=", - "owner": "stoeffel", - "repo": "nix-test-runner", - "rev": "c45d45b11ecef3eb9d834c3b6304c05c49b06ca2", - "type": "github" - }, - "original": { - "owner": "stoeffel", - "repo": "nix-test-runner", - "type": "github" - } - }, - "nix-test-runner_3": { - "flake": false, - "locked": { - "lastModified": 1588761593, - "narHash": "sha256-FKJykltAN/g3eIceJl4SfDnnyuH2jHImhMrXS2KvGIs=", - "owner": "stoeffel", - "repo": "nix-test-runner", - "rev": "c45d45b11ecef3eb9d834c3b6304c05c49b06ca2", - "type": "github" - }, - "original": { - "owner": "stoeffel", - "repo": "nix-test-runner", - "type": "github" - } - }, "nixpkgs": { - "locked": { - "lastModified": 1743014863, - "narHash": "sha256-jAIUqsiN2r3hCuHji80U7NNEafpIMBXiwKlSrjWMlpg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "bd3bac8bfb542dbde7ffffb6987a1a1f9d41699f", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { "locked": { "lastModified": 1760782625, "narHash": "sha256-qeSmHF66cMiHObiBhm8IngmqDBEcqNdBSSoAjuE6tTw=", @@ -760,197 +335,32 @@ "type": "github" } }, - "nixpkgs_3": { - "locked": { - "lastModified": 1700612854, - "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_4": { - "locked": { - "lastModified": 1715534503, - "narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "2057814051972fa1453ddfb0d98badbea9b83c06", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_5": { - "locked": { - "lastModified": 1715534503, - "narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "2057814051972fa1453ddfb0d98badbea9b83c06", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_6": { - "locked": { - "lastModified": 1719506693, - "narHash": "sha256-C8e9S7RzshSdHB7L+v9I51af1gDM5unhJ2xO1ywxNH8=", - "path": "/nix/store/4p0avw1s3vf27hspgqsrqs37gxk4i83i-source", - "rev": "b2852eb9365c6de48ffb0dc2c9562591f652242a", - "type": "path" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_7": { - "locked": { - "lastModified": 1719506693, - "narHash": "sha256-C8e9S7RzshSdHB7L+v9I51af1gDM5unhJ2xO1ywxNH8=", - "path": "/nix/store/4p0avw1s3vf27hspgqsrqs37gxk4i83i-source", - "rev": "b2852eb9365c6de48ffb0dc2c9562591f652242a", - "type": "path" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_8": { - "locked": { - "lastModified": 1729850857, - "narHash": "sha256-WvLXzNNnnw+qpFOmgaM3JUlNEH+T4s22b5i2oyyCpXE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "41dea55321e5a999b17033296ac05fe8a8b5a257", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "sonnenshift", "crate2nix", - "crate2nix_stable", - "crate2nix_stable", "flake-compat" ], - "gitignore": "gitignore", + "gitignore": [ + "sonnenshift", + "crate2nix", + "cachix", + "git-hooks", + "gitignore" + ], "nixpkgs": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "crate2nix_stable", - "nixpkgs" - ], - "nixpkgs-stable": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1719259945, - "narHash": "sha256-F1h+XIsGKT9TkGO3omxDLEb/9jOOsI6NnzsXFsZhry4=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "0ff4381bbb8f7a52ca4a851660fc7a437a4c6e07", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "pre-commit-hooks_2": { - "inputs": { - "flake-compat": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "flake-compat" - ], - "gitignore": "gitignore_2", - "nixpkgs": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "nixpkgs" - ], - "nixpkgs-stable": [ - "sonnenshift", - "crate2nix", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1719259945, - "narHash": "sha256-F1h+XIsGKT9TkGO3omxDLEb/9jOOsI6NnzsXFsZhry4=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "0ff4381bbb8f7a52ca4a851660fc7a437a4c6e07", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "pre-commit-hooks_3": { - "inputs": { - "flake-compat": [ - "sonnenshift", - "crate2nix", - "flake-compat" - ], - "flake-utils": "flake-utils_5", - "gitignore": "gitignore_3", - "nixpkgs": [ - "sonnenshift", - "crate2nix", - "nixpkgs" - ], - "nixpkgs-stable": [ "sonnenshift", "crate2nix", "nixpkgs" ] }, "locked": { - "lastModified": 1712055707, - "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", + "lastModified": 1762868777, + "narHash": "sha256-QqS72GvguP56oKDNUckWUPNJHjsdeuXh5RyoKz0wJ+E=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", + "rev": "c5c3147730384576196fb5da048a6e45dee10d56", "type": "github" }, "original": { @@ -961,7 +371,10 @@ }, "purescript-overlay": { "inputs": { - "flake-compat": "flake-compat_5", + "flake-compat": [ + "deploy-rs", + "flake-compat" + ], "nixpkgs": [ "tlaternet-webserver", "dream2nix", @@ -970,11 +383,11 @@ "slimlock": "slimlock" }, "locked": { - "lastModified": 1728546539, - "narHash": "sha256-Sws7w0tlnjD+Bjck1nv29NjC5DbL6nH5auL9Ex9Iz2A=", + "lastModified": 1750754571, + "narHash": "sha256-qquerCyD6WhVccAV0qI7NFGwSN7rXslhogPrTaFvWto=", "owner": "thomashoneyman", "repo": "purescript-overlay", - "rev": "4ad4c15d07bd899d7346b331f377606631eb0ee4", + "rev": "81513816356c43c6ef604abdf5da41834306a2d5", "type": "github" }, "original": { @@ -984,18 +397,23 @@ } }, "pyproject-nix": { - "flake": false, + "inputs": { + "nixpkgs": [ + "tlaternet-webserver", + "dream2nix", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1702448246, - "narHash": "sha256-hFg5s/hoJFv7tDpiGvEvXP0UfFvFEDgTdyHIjDVHu1I=", - "owner": "davhau", + "lastModified": 1762427963, + "narHash": "sha256-CkPlAbIQ87wmjy5qHibfzk4DmMGBNqFer+lLfXjpP5M=", + "owner": "pyproject-nix", "repo": "pyproject.nix", - "rev": "5a06a2697b228c04dd2f35659b4b659ca74f7aeb", + "rev": "4540ea004e04fcd12dd2738d51383d10f956f7b9", "type": "github" }, "original": { - "owner": "davhau", - "ref": "dream2nix", + "owner": "pyproject-nix", "repo": "pyproject.nix", "type": "github" } @@ -1004,8 +422,9 @@ "inputs": { "deploy-rs": "deploy-rs", "disko": "disko", + "flint": "flint", "foundryvtt": "foundryvtt", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs", "sonnenshift": "sonnenshift", "sops-nix": "sops-nix", "tlaternet-webserver": "tlaternet-webserver" @@ -1107,81 +526,6 @@ "type": "github" } }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_3": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_4": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_5": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_6": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "tlaternet-webserver": { "inputs": { "dream2nix": "dream2nix", diff --git a/flake.nix b/flake.nix index 76d612f..386de98 100644 --- a/flake.nix +++ b/flake.nix @@ -3,19 +3,44 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05-small"; + + ## Nix/OS utilities + disko = { url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; - deploy-rs.url = "github:serokell/deploy-rs"; + + deploy-rs = { + url = "github:serokell/deploy-rs"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + sops-nix = { url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - tlaternet-webserver = { - url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git"; + + ## Programs + + flint = { + url = "github:NotAShelf/flint"; inputs.nixpkgs.follows = "nixpkgs"; }; + + ## Services + + tlaternet-webserver = { + url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git"; + inputs = { + nixpkgs.follows = "nixpkgs"; + dream2nix.inputs = { + nixpkgs.follows = "nixpkgs"; + purescript-overlay.inputs.flake-compat.follows = "deploy-rs/flake-compat"; + }; + }; + }; + foundryvtt = { url = "github:reckenrode/nix-foundryvtt"; inputs.nixpkgs.follows = "nixpkgs"; @@ -23,7 +48,20 @@ sonnenshift = { url = "git+ssh://git@github.com/sonnenshift/battery-manager"; - inputs.nixpkgs.follows = "nixpkgs"; + inputs = { + nixpkgs.follows = "nixpkgs"; + + crate2nix.inputs = { + nixpkgs.follows = "nixpkgs"; + flake-compat.follows = "deploy-rs/flake-compat"; + cachix.inputs.nixpkgs.follows = "nixpkgs"; + pre-commit-hooks.inputs.gitignore.follows = "sonnenshift/crate2nix/cachix/git-hooks/gitignore"; + + # Yes, they do this insanity: + # https://github.com/nix-community/crate2nix/issues/371 + crate2nix_stable.follows = "sonnenshift/crate2nix"; + }; + }; }; }; @@ -90,7 +128,7 @@ ######### # Tests # ######### - checks.${system} = import ./checks (inputs // { inherit system; }); + checks = import ./checks { flake-inputs = inputs; }; ########################### # Garbage collection root # From d82c3533294e405f31d3464baa981563760a3c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Nov 2025 05:16:12 +0800 Subject: [PATCH 3/4] fix(vm): Set disk size declaratively --- configuration/hardware-specific/vm.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/configuration/hardware-specific/vm.nix b/configuration/hardware-specific/vm.nix index 71870fb..aa360aa 100644 --- a/configuration/hardware-specific/vm.nix +++ b/configuration/hardware-specific/vm.nix @@ -48,6 +48,7 @@ memorySize = 3941; cores = 2; graphics = false; + diskSize = 1024 * 20; }; virtualisation.qemu = { From 767a14ab6e0c54d5e8ca98d059583e8ff06a47db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Nov 2025 04:07:10 +0800 Subject: [PATCH 4/4] refactor(nginx): Clean up nginx configuration --- configuration/default.nix | 2 +- configuration/nginx.nix | 77 ------------------ configuration/nginx/default.nix | 22 +++++ configuration/nginx/logging.nix | 84 ++++++++++++++++++++ configuration/nginx/ssl.nix | 68 ++++++++++++++++ configuration/services/metrics/exporters.nix | 29 +------ modules/default.nix | 7 +- modules/nginxExtensions.nix | 59 -------------- 8 files changed, 177 insertions(+), 171 deletions(-) delete mode 100644 configuration/nginx.nix create mode 100644 configuration/nginx/default.nix create mode 100644 configuration/nginx/logging.nix create mode 100644 configuration/nginx/ssl.nix delete mode 100644 modules/nginxExtensions.nix diff --git a/configuration/default.nix b/configuration/default.nix index f2d1615..54f17c2 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -27,7 +27,7 @@ ./services/wireguard.nix # ./services/starbound.nix -- Not currently used ./services/postgres.nix - ./nginx.nix + ./nginx ./sops.nix ]; diff --git a/configuration/nginx.nix b/configuration/nginx.nix deleted file mode 100644 index 935b5ac..0000000 --- a/configuration/nginx.nix +++ /dev/null @@ -1,77 +0,0 @@ -{ config, lib, ... }: -{ - services = { - nginx = { - enable = true; - recommendedTlsSettings = true; - recommendedOptimisation = true; - recommendedGzipSettings = true; - recommendedProxySettings = true; - clientMaxBodySize = "10G"; - - statusPage = true; # For metrics, should be accessible only from localhost - - commonHttpConfig = '' - log_format upstream_time '$remote_addr - $remote_user [$time_local] ' - '"$request" $status $body_bytes_sent ' - '"$http_referer" "$http_user_agent" ' - 'rt=$request_time uct="$upstream_connect_time" ' - 'uht="$upstream_header_time" urt="$upstream_response_time"'; - ''; - }; - - logrotate.settings = { - # Override the default, just keep fewer logs - nginx.rotate = 6; - } - // lib.mapAttrs' ( - virtualHost: _: - lib.nameValuePair "/var/log/nginx/${virtualHost}/access.log" { - frequency = "daily"; - rotate = 2; - compress = true; - delaycompress = true; - su = "${config.services.nginx.user} ${config.services.nginx.group}"; - postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`"; - } - ) config.services.nginx.virtualHosts; - - backups.acme = { - user = "acme"; - paths = lib.mapAttrsToList ( - virtualHost: _: "/var/lib/acme/${virtualHost}" - ) config.services.nginx.virtualHosts; - }; - }; - - systemd.tmpfiles.rules = lib.mapAttrsToList ( - virtualHost: _: - # - "d /var/log/nginx/${virtualHost} 0750 ${config.services.nginx.user} ${config.services.nginx.group}" - ) config.services.nginx.virtualHosts; - - security.acme = { - defaults.email = "tm@tlater.net"; - acceptTerms = true; - - certs."tlater.net" = { - extraDomainNames = [ - "*.tlater.net" - "tlater.com" - "*.tlater.com" - ]; - dnsProvider = "porkbun"; - group = "ssl-cert"; - credentialFiles = { - PORKBUN_API_KEY_FILE = config.sops.secrets."porkbun/api-key".path; - PORKBUN_SECRET_API_KEY_FILE = config.sops.secrets."porkbun/secret-api-key".path; - }; - }; - }; - - users.groups.ssl-cert = { }; - - systemd.services.nginx.serviceConfig.SupplementaryGroups = [ - config.security.acme.certs."tlater.net".group - ]; -} diff --git a/configuration/nginx/default.nix b/configuration/nginx/default.nix new file mode 100644 index 0000000..dab0259 --- /dev/null +++ b/configuration/nginx/default.nix @@ -0,0 +1,22 @@ +{ lib, ... }: +{ + imports = [ + ./logging.nix + ./ssl.nix + ]; + + options.services.nginx.domain = lib.mkOption { + type = lib.types.str; + description = "The base domain name to append to virtual domain names"; + }; + + config.services.nginx = { + enable = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + recommendedProxySettings = true; + clientMaxBodySize = "10G"; + statusPage = true; # For metrics, should be accessible only from localhost + }; +} diff --git a/configuration/nginx/logging.nix b/configuration/nginx/logging.nix new file mode 100644 index 0000000..0c6a955 --- /dev/null +++ b/configuration/nginx/logging.nix @@ -0,0 +1,84 @@ +{ config, lib, ... }: +let + hostNames = lib.attrNames config.services.nginx.virtualHosts; + logPath = name: "/var/log/nginx/${name}/access.log"; + logFormat = lib.concatStringsSep " " [ + "$remote_addr - $remote_user [$time_local]" + ''"$request" $status $body_bytes_sent'' + ''"$http_referer" "$http_user_agent"'' + ''rt=$request_time uct="$upstream_connect_time"'' + ''uht="$upstream_header_time" urt="$upstream_response_time"'' + ]; +in +{ + # Extend the default configuration for nginx virtual hosts; we'd + # like to create log files for each of them, so that the prometheus + # nginxlog exporter can process per-host logs. + options.services.nginx.virtualHosts = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.submodule ( + { name, ... }: + { + config.extraConfig = '' + access_log ${logPath name} upstream_time; + ''; + } + ) + ); + }; + + config = { + # Create directories for host-specific logs with systemd tmpfiles + systemd.tmpfiles.settings."10-nginx-logs" = lib.listToAttrs ( + map ( + name: + lib.nameValuePair "/var/log/nginx/${name}" { + d = { + inherit (config.services.nginx) user group; + mode = "0750"; + }; + } + ) hostNames + ); + + services = { + # Set the nginx-wide log format + nginx.commonHttpConfig = '' + log_format upstream_time '${logFormat}'; + ''; + + # Set up nginxlog to read the file and log format defined above + # for each virtual host + prometheus.exporters.nginxlog = { + enable = true; + listenAddress = "127.0.0.1"; + group = "nginx"; + + settings.namespaces = map (name: { + inherit name; + metrics_override.prefix = "nginxlog"; + namespace_label = "vhost"; + format = logFormat; + source.files = [ (logPath name) ]; + }) hostNames; + }; + + logrotate.settings = { + # Override the nginx module default, just keep fewer logs + nginx.rotate = 6; + + # Configure logrotate for host-specific logs + nginxVirtualHosts = { + files = map logPath hostNames; + + frequency = "daily"; + rotate = 2; + compress = true; + delaycompress = true; + su = "${config.services.nginx.user} ${config.services.nginx.group}"; + postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`"; + }; + }; + }; + }; +} diff --git a/configuration/nginx/ssl.nix b/configuration/nginx/ssl.nix new file mode 100644 index 0000000..4cea508 --- /dev/null +++ b/configuration/nginx/ssl.nix @@ -0,0 +1,68 @@ +{ + pkgs, + config, + lib, + ... +}: +{ + options = { + # Add a custom per-host option to enable HSTS + services.nginx.virtualHosts = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.submodule ( + { config, ... }: + { + options.enableHSTS = lib.mkEnableOption "HSTS"; + config.extraConfig = lib.mkIf config.enableHSTS '' + add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; + ''; + } + ) + ); + }; + }; + + config = { + # Certificate settings + security.acme = { + defaults.email = "tm@tlater.net"; + acceptTerms = true; + + certs."tlater.net" = { + extraDomainNames = [ + "*.tlater.net" + "tlater.com" + "*.tlater.com" + ]; + dnsProvider = "porkbun"; + group = config.users.groups.ssl-cert.name; + credentialFiles = { + PORKBUN_API_KEY_FILE = config.sops.secrets."porkbun/api-key".path; + PORKBUN_SECRET_API_KEY_FILE = config.sops.secrets."porkbun/secret-api-key".path; + }; + }; + }; + users.groups.ssl-cert = { }; + + # Back up the SSL certificate, just in case + services.backups.acme = { + user = "acme"; + paths = [ "/var/lib/acme/tlater.net" ]; + }; + + systemd.services = { + nginx.serviceConfig.SupplementaryGroups = [ config.security.acme.certs."tlater.net".group ]; + + # Don't attempt to retrieve a certificate if the domain name + # doesn't *actually* match the cert name + # + # TODO(tlater): Set up pebble to retrieve certs "properly" + # instead + "acme-tlater.net".serviceConfig.ExecCondition = + let + confirm = ''[[ "tlater.net" = "${config.services.nginx.domain}" ]]''; + in + ''${pkgs.runtimeShell} -c '${confirm}' ''; + }; + }; +} diff --git a/configuration/services/metrics/exporters.nix b/configuration/services/metrics/exporters.nix index 52c2a46..ea57c9b 100644 --- a/configuration/services/metrics/exporters.nix +++ b/configuration/services/metrics/exporters.nix @@ -1,9 +1,4 @@ -{ - config, - pkgs, - lib, - ... -}: +{ pkgs, ... }: let yaml = pkgs.formats.yaml { }; in @@ -68,28 +63,6 @@ in enable = true; listenAddress = "127.0.0.1"; }; - - nginxlog = { - enable = true; - listenAddress = "127.0.0.1"; - group = "nginx"; - - settings.namespaces = lib.mapAttrsToList (name: _: { - inherit name; - metrics_override.prefix = "nginxlog"; - namespace_label = "vhost"; - - format = lib.concatStringsSep " " [ - "$remote_addr - $remote_user [$time_local]" - ''"$request" $status $body_bytes_sent'' - ''"$http_referer" "$http_user_agent"'' - ''rt=$request_time uct="$upstream_connect_time"'' - ''uht="$upstream_header_time" urt="$upstream_response_time"'' - ]; - - source.files = [ "/var/log/nginx/${name}/access.log" ]; - }) config.services.nginx.virtualHosts; - }; }; # TODO(tlater): diff --git a/modules/default.nix b/modules/default.nix index 89f1752..9483c66 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,6 +1 @@ -{ - imports = [ - ./crowdsec - ./nginxExtensions.nix - ]; -} +{ imports = [ ./crowdsec ]; } diff --git a/modules/nginxExtensions.nix b/modules/nginxExtensions.nix deleted file mode 100644 index bd505d3..0000000 --- a/modules/nginxExtensions.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: -{ - options = { - services.nginx.domain = lib.mkOption { - type = lib.types.str; - description = "The base domain name to append to virtual domain names"; - }; - - services.nginx.virtualHosts = - let - extraVirtualHostOptions = - { name, config, ... }: - { - options = { - enableHSTS = lib.mkEnableOption "Enable HSTS"; - - addAccessLog = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Add special logging to `/var/log/nginx/''${serverName}` - ''; - }; - }; - - config = { - extraConfig = lib.concatStringsSep "\n" [ - (lib.optionalString config.enableHSTS '' - add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; - '') - (lib.optionalString config.addAccessLog '' - access_log /var/log/nginx/${name}/access.log upstream_time; - '') - ]; - }; - }; - in - lib.mkOption { type = lib.types.attrsOf (lib.types.submodule extraVirtualHostOptions); }; - }; - - config = { - # Don't attempt to run acme if the domain name is not tlater.net - systemd.services = - let - confirm = ''[[ "tlater.net" = ${config.services.nginx.domain} ]]''; - in - lib.mapAttrs' ( - cert: _: - lib.nameValuePair "acme-${cert}" { - serviceConfig.ExecCondition = ''${pkgs.runtimeShell} -c '${confirm}' ''; - } - ) config.security.acme.certs; - }; -}