diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5d8bea90..62604347 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 2026-09-06 + +- **Configured OpenID Connect (OIDC) authentication for Actual Budget**: + - Configured `services.actual.settings` with `loginMethod = "openid"` and `openId` settings pointing to Pocket ID (`auth.masu.rs`), using client ID `92afe9f8-7ef6-42ab-8a06-701df3c7179d`. + - Added secret management for `actualbudget-oidc-secret.age` via `secrets.actualbudget-oidc-secret`, set with owner `actualbudget` and group `shared` (0440). + - Configured `systemd.services.actual` to order after the decrypted secret service and granted the dynamic unit access via `SupplementaryGroups = [ "shared" ]` and `PrivateUsers = false`. + - Updated `docs/oidc-services.md` with the verified callback URI (`https://money.masu.rs/openid/callback`) and NixOS configuration snippet. + ## 2026-08-29 (root cause found and fixed) - **Root-caused and fixed the recurring post-TUI typing lag** (fish + Zellij + Ghostty) using a `lag-triage` capture from a live lagging shell plus a deterministic PTY reproduction (`presets/programs/lag-triage/upstream_repro.py`): diff --git a/docs/oidc-services.md b/docs/oidc-services.md index 44183e28..7f1eb937 100644 --- a/docs/oidc-services.md +++ b/docs/oidc-services.md @@ -34,7 +34,7 @@ These services support OpenID Connect natively without requiring external authen | **Mealie** | `cooking.masu.rs` | Native core feature | NixOS env vars (`OIDC_AUTH_ENABLED`, etc.) | | **Karakeep / Hoarder** | `keep.masu.rs` | Native (NextAuth OIDC) | NixOS env vars (`OAUTH_WELLKNOWN_URL`, etc.) | | **Audiobookshelf** | `read.masu.rs` | Native core feature (v2.3+) | Web UI (Settings → Authentication) | -| **Actual Budget** | `money.masu.rs` | Native core feature (v24.3+) | NixOS env vars (`ACTUAL_LOGIN_METHOD=openid`) | +| **Actual Budget** | `money.masu.rs` | Native core feature (v24.3+) | NixOS config (`services.actual.settings.openId`) | --- @@ -218,16 +218,18 @@ All client secrets should be encrypted with `agenix` under the respective servic - Match user by email or username ### 9. Actual Budget (`money.masu.rs`) -- **Pocket ID Redirect URI:** `https://money.masu.rs/oauth/callback` +- **Pocket ID Redirect URI:** `https://money.masu.rs/openid/callback` - **Setup in `actualbudget/actualbudget.nix`:** ```nix services.actual.settings = { - # Passed via environment or configuration - ACTUAL_LOGIN_METHOD = "openid"; - ACTUAL_OPENID_DISCOVERY_URL = "https://auth.masu.rs/.well-known/openid-configuration"; - ACTUAL_OPENID_CLIENT_ID = "actual"; - ACTUAL_OPENID_CLIENT_SECRET = "..."; - ACTUAL_OPENID_SERVER_HOSTNAME = "https://money.masu.rs"; + loginMethod = "openid"; + openId = { + discoveryURL = "https://${hostnames.auth}/.well-known/openid-configuration"; + client_id = "92afe9f8-7ef6-42ab-8a06-701df3c7179d"; + client_secret._secret = config.secrets.actualbudget-oidc-secret.dest; + server_hostname = "https://${hostnames.budget}"; + authMethod = "openid"; + }; }; ``` *Note:* The optional end-to-end budget encryption password remains separate from the server authentication. diff --git a/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget-oidc-secret.age b/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget-oidc-secret.age new file mode 100644 index 00000000..fc76b4db --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget-oidc-secret.age @@ -0,0 +1,17 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBycCtF +S1ErMkNoME1ZNzYramZ6cFJGL1VLbU1sSnVBaTA2Y3B2M1FUYTM0Cnl1a0dmdEpt +U3puRS9RUEUyVVBDelRRRGlGQXdWQzc4cHprZGNRb2RuYmcKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIDJ1M1dmTnB4Vzg3WDZ3QzZDZ1phYTU4YUk0U1VmV2M5cHZ2bENE +eEE5aDQKODFrOWJBWjE0WFJKRTVrb2dlTmVHdEVHeVc4MU9GRHhTY1l5Mzh1YnZo +dwotPiBzc2gtZWQyNTUxOSBuanZYNUEgM2JNTmVuTCtiSnNOS2UybE5qQXptcW92 +QngyaGh5Y0VqOGZEaWpkazYzawpjZmExWmF5MjV0NE05ZXVzenhYVXpRaGg4R25x +QkpFa080S3haTXpTUi80Ci0+IHNzaC1lZDI1NTE5IENxSU9VQSBQcjgrV0c3S21I +RXY5WnlSdWRML1g4ZmtvNWVmTGNwb3owZUFWN0s0ckhZCm1PbGtKY1hOanBGU0V6 +MzRrd3lPSUIrUVY3ZW5VTzFrWnJjblNvZmVIYk0KLT4gc3NoLWVkMjU1MTkgejFP +Y1p3IGdoRHVhbG52OE5wUEFwWjlvb0xZSUpOS0loNm1QOWZ0N2RGZ2xMcW5RQXcK +UUpNdDh1aUN0cHM2N0M3bGMvcjIwT2YrV01sdjdBQThkM3BxQ1hXY1A3bwotLS0g +K21sZndObVJLdkNBR3IvWHZ3c0RjSEJQajFUV2tFUmNXWDQ3RU1DNzJKcwon7wF2 +i2V9/fXS9QBfTvUJGP9MQ1gCe+UxstI3IPv+ODudHLeCGT0JoxkN6DZtayxKYYJn +iKghS8tUNdzshOBqpA== +-----END AGE ENCRYPTED FILE----- diff --git a/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix b/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix index 4cc0e04d..f25f11bd 100644 --- a/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix +++ b/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix @@ -32,6 +32,22 @@ in enable = true; settings = { port = cfg.port; + loginMethod = "openid"; + openId = { + discoveryURL = "https://${hostnames.auth}/.well-known/openid-configuration"; + client_id = "92afe9f8-7ef6-42ab-8a06-701df3c7179d"; + client_secret._secret = config.secrets.actualbudget-oidc-secret.dest; + server_hostname = "https://${hostnames.budget}"; + authMethod = "openid"; + }; + }; + }; + + systemd.services.actual = { + after = [ "actualbudget-oidc-secret-secret.service" ]; + serviceConfig = { + PrivateUsers = lib.mkForce false; + SupplementaryGroups = [ "shared" ]; }; }; @@ -107,6 +123,17 @@ in owner = builtins.toString config.users.users.actualbudget.uid; group = builtins.toString config.users.users.actualbudget.uid; }; + secrets.actualbudget-oidc-secret = { + source = ./actualbudget-oidc-secret.age; + dest = "${config.secretsDirectory}/actualbudget-oidc-secret"; + owner = config.users.users.actualbudget.name; + group = config.users.groups.shared.name; + permissions = "0440"; + }; + systemd.services.actualbudget-oidc-secret-secret = { + requiredBy = [ "actual.service" ]; + before = [ "actual.service" ]; + }; # Allow web traffic to Caddy nmasur.presets.services.caddy.routes = lib.mkAfter [