From dc19d20d737f35b4046857000f73f63c1f0ae340 Mon Sep 17 00:00:00 2001 From: kurogeek Date: Wed, 30 Jul 2025 10:21:32 +0700 Subject: [PATCH] rework pocket-id to be more generic --- inventories/default.nix | 1 - machines/b4l/services/pocket-id.nix | 35 ++++++++ modules/clan/pocket-id/default.nix | 80 +++++++------------ modules/clan/pocket-id/flake-module.nix | 19 +++++ modules/clan/pocket-id/tests/vm/default.nix | 34 ++++++++ .../tests/vm/sops/machines/server/key.json | 6 ++ .../vm/sops/secrets/server-age.key/secret | 15 ++++ .../sops/secrets/server-age.key/users/admin | 1 + .../tests/vm/sops/users/admin/key.json | 4 + .../pocket-id/encryption-key/machines/server | 1 + .../server/pocket-id/encryption-key/secret | 19 +++++ .../pocket-id/encryption-key/users/admin | 1 + .../b4l/b4l-pocket-id/subdomain/value | 1 + .../b4l/pocket-id/encryption-key/secret | 10 +-- 14 files changed, 169 insertions(+), 58 deletions(-) create mode 100644 machines/b4l/services/pocket-id.nix create mode 100644 modules/clan/pocket-id/flake-module.nix create mode 100644 modules/clan/pocket-id/tests/vm/default.nix create mode 100755 modules/clan/pocket-id/tests/vm/sops/machines/server/key.json create mode 100644 modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/secret create mode 120000 modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/users/admin create mode 100644 modules/clan/pocket-id/tests/vm/sops/users/admin/key.json create mode 120000 modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/machines/server create mode 100644 modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/secret create mode 120000 modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/users/admin create mode 100644 vars/per-machine/b4l/b4l-pocket-id/subdomain/value diff --git a/inventories/default.nix b/inventories/default.nix index d0280e9..bbff363 100644 --- a/inventories/default.nix +++ b/inventories/default.nix @@ -8,7 +8,6 @@ { clan = { modules = { - pocket-id = ../modules/clan/pocket-id; stirling-pdf = ../modules/clan/stirling-pdf; actual-budget = ../modules/clan/actual-budget; victoria-metrics = ../modules/clan/victoria-metrics; diff --git a/machines/b4l/services/pocket-id.nix b/machines/b4l/services/pocket-id.nix new file mode 100644 index 0000000..d610209 --- /dev/null +++ b/machines/b4l/services/pocket-id.nix @@ -0,0 +1,35 @@ +{ config, ... }: +let + pidDomain = "${config.clan.core.vars.generators.b4l-pocket-id.files.subdomain.value}.${config.networking.fqdn}"; +in +{ + clan.core.vars.generators.b4l-pocket-id = { + files.subdomain.secret = false; + + prompts = { + subdomain = { + persist = true; + type = "line"; + description = "Sub-domain for Pocket-ID app. Default:(auth)"; + }; + }; + + script = ''cat $prompts/subdomain || echo -n "auth" > $out/subdomain''; + }; + + services.pocket-id = { + settings = { + APP_ENV = "production"; + APP_URL = "https://${pidDomain}"; + TRUST_PROXY = true; + }; + }; + + services.nginx.virtualHosts."${pidDomain}" = { + useACMEHost = "${config.networking.fqdn}"; + forceSSL = true; + locations."/" = { + proxyPass = "http://localhost:${builtins.toString config.services.pocket-id.settings.PORT}"; + }; + }; +} diff --git a/modules/clan/pocket-id/default.nix b/modules/clan/pocket-id/default.nix index 9ba268c..700589c 100644 --- a/modules/clan/pocket-id/default.nix +++ b/modules/clan/pocket-id/default.nix @@ -1,4 +1,4 @@ -{ lib, ... }: +{ ... }: { _class = "clan.service"; manifest.name = "pocket-id"; @@ -6,64 +6,40 @@ manifest.categories = [ "System" ]; roles.default = { - interface.options = { - domain = lib.mkOption { - type = lib.types.str; - default = "auth"; - description = ""; - }; - }; - perInstance = + perInstance.nixosModule = { - settings, + config, + pkgs, + lib, ... }: { - nixosModule = - { - config, - pkgs, - ... - }: - let - domain = "${settings.domain}.${config.networking.fqdn}"; - in - { - clan.core.vars.generators.pocket-id = { - files = { - encryption-key = { - owner = "${config.services.pocket-id.user}"; - group = "${config.services.pocket-id.group}"; - secret = true; - }; - }; - runtimeInputs = [ pkgs.pwgen ]; - script = '' - pwgen -s 32 1 > $out/encryption-key - ''; + clan.core.vars.generators.pocket-id = { + files = { + encryption-key = { + owner = "${config.services.pocket-id.user}"; + group = "${config.services.pocket-id.group}"; + secret = true; }; - services.pocket-id = { - enable = true; - settings = { - ENCRYPTION_KEY_FILE = config.clan.core.vars.generators.pocket-id.files.encryption-key.path; - APP_ENV = "production"; - APP_URL = "https://${domain}"; - TRUST_PROXY = true; - PORT = 1411; - - UI_CONFIG_DISABLED = true; - }; - }; - services.nginx.virtualHosts."${domain}" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://localhost:${builtins.toString config.services.pocket-id.settings.PORT}"; - }; - }; - }; + runtimeInputs = [ pkgs.pwgen ]; + script = '' + pwgen -s 32 1 > $out/encryption-key + ''; + }; + + clan.core.state.pocket-id.folders = [ config.services.pocket-id.dataDir ]; + + services.pocket-id = { + enable = lib.mkDefault true; + settings = { + ENCRYPTION_KEY_FILE = config.clan.core.vars.generators.pocket-id.files.encryption-key.path; + PORT = lib.mkDefault 1411; + ANALYTICS_DISABLED = lib.mkDefault true; + UI_CONFIG_DISABLED = lib.mkDefault true; + }; + }; }; }; } diff --git a/modules/clan/pocket-id/flake-module.nix b/modules/clan/pocket-id/flake-module.nix new file mode 100644 index 0000000..812f7ac --- /dev/null +++ b/modules/clan/pocket-id/flake-module.nix @@ -0,0 +1,19 @@ +{ lib, ... }: +let + module = lib.modules.importApply ./default.nix { }; +in +{ + clan.modules = { + pocket-id = module; + }; + + perSystem = + { ... }: + { + clan.nixosTests.pocket-id = { + imports = [ ./tests/vm/default.nix ]; + + clan.modules."@clan/pocket-id" = module; + }; + }; +} diff --git a/modules/clan/pocket-id/tests/vm/default.nix b/modules/clan/pocket-id/tests/vm/default.nix new file mode 100644 index 0000000..64ef3b4 --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/default.nix @@ -0,0 +1,34 @@ +{ ... }: +{ + name = "service-pocket-id"; + + clan = { + directory = ./.; + inventory = { + machines.server = { }; + + instances = { + pocket-id-test = { + module.name = "@clan/pocket-id"; + module.input = "self"; + roles.default.machines."server" = { }; + }; + }; + }; + }; + + nodes = { + server = { + services.pocket-id = { }; + }; + }; + + testScript = '' + start_all() + + server.wait_for_unit("pocket-id") + + # Check that garage is running + server.succeed("systemctl status pocket-id") + ''; +} diff --git a/modules/clan/pocket-id/tests/vm/sops/machines/server/key.json b/modules/clan/pocket-id/tests/vm/sops/machines/server/key.json new file mode 100755 index 0000000..521ad59 --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/sops/machines/server/key.json @@ -0,0 +1,6 @@ +[ + { + "publickey": "age1jvhs79a367ynhupy6gndyafg5f6wzrsa3p3r27d8y4zpvlp5vd6qwysnc2", + "type": "age" + } +] \ No newline at end of file diff --git a/modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/secret b/modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/secret new file mode 100644 index 0000000..8fccb44 --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/secret @@ -0,0 +1,15 @@ +{ + "data": "ENC[AES256_GCM,data:MheRz91AzSqUV0gz3PHdort06igblp8dVku2GIeXbBiTpG3Dnlqzw6QEvTeRVtZ4ol0gHS8CQQ4Lc4H9IyHGiTfJkSUM7pXY/vM=,iv:mMibIfA6gqvJlbau9sKkjRoYrDcqCpTG0b+jrZCHIkE=,tag:MN5I9AO1U7sJfq/9GxSFCg==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1dnVqRXVibTFYeUlsc09J\nQnRSRVE0NklWWFNlbHZaaWJ3dDlEaTJKVkZnCnJEZHhoSzd3T3NEVjFjY0NkRFNq\nL1owbmR0SENSWVQxOXVlNWJFb0JsSEEKLS0tIHhESEI2Y3MzMU9WRzhYNWZhUUd2\nTVpldG5qbDF6UG9jNnBRTnZRdzAweDAKl4FpFTp7NyTHXJEF7tIO0CnsgTY4maJ2\n7KfQRwQuhW73WqVdzJSZ7i/Xapwglx0ISBvSEDgBTiQhFlBLCMEzYg==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-07-29T09:50:44Z", + "mac": "ENC[AES256_GCM,data:lZ7SAQkkH441L3Ss9nEI1fm6SgcysIcOBg9it0m80CiNhtittsFNcP7l0ApkIBQLhMsan93bLMG3kcDKzqxld3XDRPUwlJkKElh8Dc8q7qqtOqgKNnsFDcx4Zh3HdiTPywyIBnUMYAul4tVPpEzqh1GSD1GF9fsBxLiwxBwalY4=,iv:wmhz1k5LMNNxuacQj+A5FryJwzqxpXf5AnFoeL1TF4k=,tag:cl5OcxGYvC6DGQDRuhqRRw==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/users/admin b/modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/users/admin new file mode 120000 index 0000000..9e21a99 --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/sops/secrets/server-age.key/users/admin @@ -0,0 +1 @@ +../../../users/admin \ No newline at end of file diff --git a/modules/clan/pocket-id/tests/vm/sops/users/admin/key.json b/modules/clan/pocket-id/tests/vm/sops/users/admin/key.json new file mode 100644 index 0000000..e408aa9 --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/sops/users/admin/key.json @@ -0,0 +1,4 @@ +{ + "publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "type": "age" +} diff --git a/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/machines/server b/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/machines/server new file mode 120000 index 0000000..2bd819e --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/machines/server @@ -0,0 +1 @@ +../../../../../../sops/machines/server \ No newline at end of file diff --git a/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/secret b/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/secret new file mode 100644 index 0000000..872ac9c --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/secret @@ -0,0 +1,19 @@ +{ + "data": "ENC[AES256_GCM,data:o1BHipQXow25uobhojeSIvSaIM4SiOtjfpNBi11E7kRX,iv:mheOssj84dp1+QAG0rpdyaf5O4WWaTWh1y/DC/I9nnA=,tag:M8zSZ4GWwy5rOcOEOBbwIA==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1jvhs79a367ynhupy6gndyafg5f6wzrsa3p3r27d8y4zpvlp5vd6qwysnc2", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXaXFvL0JES28rUkhNT3Bj\neDVYZlNubC8wV1VGTHN1Vzh6NEV3YWI3L3pJClh2T0FhQURXRkRJSnFVYjVsZkdq\ncWRFL1crVm1EK2NHNUtlc1RMVlZ5aWMKLS0tIFczWUcxTWFMdkhXb2ZTZlRSNDBT\nNmxWak50M1JTV2R3M0FXclRGc0JuVjgKtsxU2a3DNhe9CeJFK+HK7lFhrpV7UuES\nqasLv4crL7+4eJFhmUxVwzT0ubPAuG3CBMbbmrYmAs2CUXWtcmqGMA==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0TGwzeUNLbkJ4bFBPVjJy\nd3pLTWRPVytrK1plQ3kzd1ZOMjBtcGJjY25nCk5mNDRxNmJjTHh4a2pBSldvQ0Y5\nUXVPbWZ1WW1QcU03MWtuL29udGFUQ1EKLS0tIHFSY1VZUGJFanhyZmN6WHJKTzEr\nbjBkVDNJUUZNZHhjSDlDZ3Z4Y0d3Q3MKHm3Ar31B2RviANl+tCeNmtYvQp5hVdui\n9Khkd3R6MshF4rZWrWhD9vea1RX9ugJJawCTU3+4zFDEWQ6XQ+tpTw==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-07-29T09:50:44Z", + "mac": "ENC[AES256_GCM,data:B3iNE0/ve2EazWNQJ6MhSaa3EAmte5GUJrVjLB7ysIoe+pf7kQy9HE2ObEypFezvbfBYAbXd+XIq8J+jTjh4X11i6/BDNsvFQKuYbTLaK+dqZzeuOQU3ntTQuhyx5qdKyXq5FtHYyJI9XsYvSFRHe2UYy4L5i6LvMoc3ka/vUHI=,iv:mXuhXp63D1UkBJX5U7RY+NqYsU5SkolDABrSDRXegFk=,tag:LJ/BnU9xKMQyr+nAAHnGFA==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/users/admin b/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/users/admin new file mode 120000 index 0000000..ca714e1 --- /dev/null +++ b/modules/clan/pocket-id/tests/vm/vars/per-machine/server/pocket-id/encryption-key/users/admin @@ -0,0 +1 @@ +../../../../../../sops/users/admin \ No newline at end of file diff --git a/vars/per-machine/b4l/b4l-pocket-id/subdomain/value b/vars/per-machine/b4l/b4l-pocket-id/subdomain/value new file mode 100644 index 0000000..9ec0d09 --- /dev/null +++ b/vars/per-machine/b4l/b4l-pocket-id/subdomain/value @@ -0,0 +1 @@ +auth \ No newline at end of file diff --git a/vars/per-machine/b4l/pocket-id/encryption-key/secret b/vars/per-machine/b4l/pocket-id/encryption-key/secret index 8d94a78..19057d5 100644 --- a/vars/per-machine/b4l/pocket-id/encryption-key/secret +++ b/vars/per-machine/b4l/pocket-id/encryption-key/secret @@ -1,18 +1,18 @@ { - "data": "ENC[AES256_GCM,data:yZrojwRKV30K+fdy6htnj/d8cHlphZw02vbeFIq6ETur,iv:ihIwFQ9p0kxhTnooSPg0eVYI4cy9k2Kf/VSI+36IfwU=,tag:/lEQKm0IrnReyr6AzLt4Lw==,type:str]", + "data": "ENC[AES256_GCM,data:Z+f/21lCA4byBi52MuwK8K0xs5KkjyZDGJo0pQL1c2pM,iv:pfqOkBOch2n8PhFQxQorC3sY4O5ri1t5lul1UOOPmxg=,tag:L1T5b8MRkNxElXf3jIcEAA==,type:str]", "sops": { "age": [ { "recipient": "age1hlzrpqqgndcthq5m5yj9egfgyet2fzrxwa6ynjzwx2r22uy6m3hqr3rd06", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjSkwwU1dTekhvYUYrV2tU\nOWhTb3NlWWVOeVJvUTVkdGE2V3IyRDlqMWhBCjJqUU5XSWxsVFVteGoycHBjOHlI\nbXpuMHo1R2VxQWVPUHR5MTBlalhVK1kKLS0tIHBFeVRDN1BycUNFa3ZTUDE3S3Jw\nNExYbjBSOUtUQkpOUUFXbHVSOVBjcUUKVP7K2EuoSmUOznpP0+Jdfwd2tfYxADg9\nIbV3lCTeimo5pOBDrVWEmgHfeZFdV892sI062MmP/EqX7iqu34hi/g==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwc2VJTWlGUEJnWlBvVHFn\neGFqUE93TmNLQ1NJZnZ1eGYyNGpWUkw1R1RRClV5T0dMVGlQK2VrTlpCQlJBV1ps\nTDFCdmE4cTdUMjZucVVGcGNmUUErWTQKLS0tIHkwODdJMWQxVFFubUV5ZTFneDFS\ndURNay9hWk81QTI5QS9RWS9HVWhNelkK0GXmKGfL2cfsziBKu6pllmHRQno6K0FA\nzHky0yt2H1w1svDfFw2+FyKHfHAwaQs+X2qXXlvIZ7jwtPj+wQXubQ==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1sg0rvgyetdcqw7j2x983fh69kdkvqsngpe5x36e5920qa7fze3cqhj4wgx", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmd0VmNS9MOEZxTXRtQlVT\ncVpZcUZNRmg0dzI1SGcybUtLNCsxNGViRjBVCkpLUlJXdTJvUlJ2d2o3eVNQelZR\nek9RSHVjSFlZbFBLRnhQS2lCTWlHWmMKLS0tIHk2dGlHZnVpVFJocFVsb1Vza25k\ncllSSkxXaGFzdDBVU3lwcE5LSEdvVzgKAjySzos4BQvf87Sk7m6Fn2b1kJzuaHuS\nlg9+ScPBjDGWVj8Ye1DKuJB44WD0nVCyECjUVNFbjhJh0bMLcIbOEQ==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoU1BqKy9HZnVrQ2ZudjBK\nWFVNQ0xPUHBOaFB2bEZvRVA0bEVQb1VYM3o0Ck95blBwckUxY3BZVkZZdHdINXlH\nYkZGdHNVQnE3ZmFja0xPaml1Y0tVWE0KLS0tIEVpNmlGanp6L1dRZGd1VVUxclZs\na3dBWmdIcFExbldFeW0zc2ZwRDVCckUKTjmYGY1RqzcijNepBd0wzDuWuywYN6oS\nQGVUhY1Tm2H+SUtIsnuNWkNsLC8LnDBIfx4DCWCYbLrC3HYmalpqPQ==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2025-07-14T06:46:06Z", - "mac": "ENC[AES256_GCM,data:Arm0JtsTlkiyfCva7MoAVQD/tMUqlS+UZprT/5IYiJli36HISEVlpr8Mc+i9Diia4wxyzq+wQqIrI/d5FG0e4FPcTi4r5X3ZyjyG6j4X+vqpIj/y6WBYjU9izXIDP5rHm7+knyhaXqzo6zXjbfvOuUG8NqdXcybA1O60xBkpq0I=,iv:j7+rlWlXtrhWlykkdygh+Luerr2xrtclgtmSQv8B9ug=,tag:nN/UaJrl/9LCS7IkIHJnrQ==,type:str]", + "lastmodified": "2025-07-30T02:42:06Z", + "mac": "ENC[AES256_GCM,data:rD5yrd5omOzzfmsA1NJgRrlP2fJEG0B7p3PrIdPJRKm3RmSHXsN7nBDfbIxMLOjU81V1z2kImnVI6kAqDeQefK6VIaqZT5h6tBMFJmUoqx55KX1PYfgICZ8wRB7nZp2LcEgtrgRnd1sjr4SbHW4s1BUxmE74WCzlDagasqqXM1s=,iv:p1KRZzDJEk3XAk+bVIYqEljqxO9p4Jx/537pQpoRnAA=,tag:WG+JVYlpCyHBXc2xycjZAQ==,type:str]", "unencrypted_suffix": "_unencrypted", "version": "3.10.2" }