From ab98a202da3f25f5690ebbc9c3d3491541b0775e Mon Sep 17 00:00:00 2001 From: Noah Masur <7386960+nmasur@users.noreply.github.com> Date: Mon, 7 Sep 2026 15:35:43 +0000 Subject: [PATCH] nextcloud: implement OIDC authentication --- docs/CHANGELOG.md | 10 +++++ docs/oidc-services.md | 42 +++++++++++++++---- .../nextcloud/nextcloud-oidc-secret.age | 17 ++++++++ .../presets/services/nextcloud/nextcloud.nix | 28 +++++++++++++ 4 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud-oidc-secret.age diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9a4a748f..44478641 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 2026-09-07 + +- **Configured OpenID Connect (OIDC) authentication for Nextcloud**: + - Added `user_oidc` to `services.nextcloud.extraApps`. + - Added secret management for `nextcloud-oidc-secret.age` via `secrets.nextcloud-oidc-secret` with owner `nextcloud` and group `nextcloud` (0440). + - Configured `systemd.services.nextcloud-oidc-secret-secret` to be required by and order before `nextcloud-setup.service`. + - Set `services.nextcloud.settings.overwriteprotocol = "https"` to ensure correct scheme handling for redirect URIs behind reverse proxy. + - Configured automated idempotent upsert of the Pocket ID provider via `systemd.services.nextcloud-setup.postStart` running `nextcloud-occ user_oidc:provider pocket-id` with client ID `c8a32c58-a781-4f14-9070-f498fdfda438`, `--clientsecret-file`, discovery URI `https://${hostnames.auth}/.well-known/openid-configuration`, `--mapping-uid="preferred_username"`, and `--unique-uid=0` to connect OIDC logins directly to existing local Nextcloud accounts. + - Updated `docs/oidc-services.md` with the verified configuration and callback URI (`https://cloud.masu.rs/apps/user_oidc/code`). + ## 2026-09-06 - **Configured OpenID Connect (OIDC) authentication for Immich**: diff --git a/docs/oidc-services.md b/docs/oidc-services.md index df9a2feb..af6b0aca 100644 --- a/docs/oidc-services.md +++ b/docs/oidc-services.md @@ -121,15 +121,39 @@ All client secrets should be encrypted with `agenix` under the respective servic ### 3. Nextcloud (`cloud.masu.rs`) - **Pocket ID Redirect URI:** `https://cloud.masu.rs/apps/user_oidc/code` - **Setup in `nextcloud/nextcloud.nix`:** - 1. Add `user_oidc` to `services.nextcloud.extraApps`. - 2. Configure the provider via `nextcloud-occ`: - ```bash - nextcloud-occ user_oidc:provider pocket-id \ - --clientid="" \ - --clientsecret="" \ - --discoveryuri="https://auth.masu.rs/.well-known/openid-configuration" \ - --scope="openid profile email" - ``` + ```nix + secrets.nextcloud-oidc-secret = { + source = ./nextcloud-oidc-secret.age; + dest = "${config.secretsDirectory}/nextcloud-oidc-secret"; + owner = "nextcloud"; + group = "nextcloud"; + permissions = "0440"; + }; + systemd.services.nextcloud-oidc-secret-secret = { + requiredBy = [ "nextcloud-setup.service" ]; + before = [ "nextcloud-setup.service" ]; + }; + + services.nextcloud = { + settings.overwriteprotocol = "https"; + extraApps = { + user_oidc = config.services.nextcloud.package.packages.apps.user_oidc; + }; + }; + + systemd.services.nextcloud-setup = { + after = [ "nextcloud-oidc-secret-secret.service" ]; + postStart = '' + ${config.services.nextcloud.occ}/bin/nextcloud-occ user_oidc:provider pocket-id \ + --clientid="c8a32c58-a781-4f14-9070-f498fdfda438" \ + --clientsecret-file="${config.secrets.nextcloud-oidc-secret.dest}" \ + --discoveryuri="https://${hostnames.auth}/.well-known/openid-configuration" \ + --scope="openid profile email" \ + --mapping-uid="preferred_username" \ + --unique-uid=0 + ''; + }; + ``` ### 4. Grafana (`metrics.masu.rs`) - **Pocket ID Redirect URI:** `https://metrics.masu.rs/login/generic_oauth` diff --git a/platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud-oidc-secret.age b/platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud-oidc-secret.age new file mode 100644 index 00000000..450d8986 --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud-oidc-secret.age @@ -0,0 +1,17 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyAzMEJs +WW9mb1E5MW5vT0tYeDhKSnFSRWZFVFdrL0d6Vk45UUVBd3JubFNvClpIRDYzM1Zh +dEtMaFNSeEF4aHY2cWpZbUNNMUw0UW93SFV0NVBMZ2wvKzgKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIDlGUUQwdlFwd1JiOE9Sb0svWTM4cDVHbGNQeFVDcUJsa0xqZGp6 +SGxkUlUKMHpPSFFSQXZSYjdwNUhnRnUxZzJVQWxLblB5MjBTZjRpM0d4NDJFSk1Z +RQotPiBzc2gtZWQyNTUxOSBuanZYNUEgK055eTE2NG9yN3FEZ1BSaTZKTGpWUmt0 +YlFWU0hjSnZ3MVZSdE12Y0VVTQovNWpGM2Y0TUlNSHRVQmRJK3VCNTBHTFAzdlYx +MXNJOVNOdTJiNlZZdWkwCi0+IHNzaC1lZDI1NTE5IENxSU9VQSArblhobTFoN1BQ +ZUhuL04yVUtTRnF1V0tPR1BVK3lzWUVrMlhJQWxmZXhZClJkUnU0QUxuRnZ3Vjg2 +TVFzdGs5dDJSbFZMQnFRamxObnFpZVBaTExFajQKLT4gc3NoLWVkMjU1MTkgejFP +Y1p3IFE1clkxRFFZbmVEV01LVWNXaVR6ZkdrcHJYUFNaSXI1STUrSmN5ejJnU2MK +STRhOWlXTFU2emVvVUkxMmxKc1FmbmJrQ1RFU3RLa2RBSUJlak5CRG1obwotLS0g +WFhjSmJxSmVMQlR0bjRKWVR1cllmQ1JjUkZZYWpTbEFzTjNQVzRvbHNJbwrrqVI1 +yl6w97t0CDhjOml46f3wlob0kztDAdOFmUSiEVfiQU0eCrfNinQg7aohu5Y8MJpD +k2Du2m/AV6aIPR47LA== +-----END AGE ENCRYPTED FILE----- diff --git a/platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud.nix b/platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud.nix index c4ffa877..b79505bc 100644 --- a/platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud.nix +++ b/platforms/nixos/modules/nmasur/presets/services/nextcloud/nextcloud.nix @@ -33,6 +33,7 @@ in # Allow access when hitting either of these hosts or IPs trusted_domains = [ hostnames.content ]; trusted_proxies = [ "127.0.0.1" ]; + overwriteprotocol = "https"; maintenance_window_start = 4; # Run jobs at 4am UTC log_type = "file"; loglevel = 1; # Include all actions in the log @@ -41,6 +42,7 @@ in extraApps = { calendar = config.services.nextcloud.package.packages.apps.calendar; contacts = config.services.nextcloud.package.packages.apps.contacts; + user_oidc = config.services.nextcloud.package.packages.apps.user_oidc; # These apps are defined and pinned by overlay in flake. # news = pkgs.nextcloudApps.news; # external = pkgs.nextcloudApps.external; @@ -211,6 +213,32 @@ in before = [ "nextcloud-setup.service" ]; }; + secrets.nextcloud-oidc-secret = { + source = ./nextcloud-oidc-secret.age; + dest = "${config.secretsDirectory}/nextcloud-oidc-secret"; + owner = "nextcloud"; + group = "nextcloud"; + permissions = "0440"; + }; + systemd.services.nextcloud-oidc-secret-secret = { + requiredBy = [ "nextcloud-setup.service" ]; + before = [ "nextcloud-setup.service" ]; + }; + + # Configure Pocket ID OIDC provider after Nextcloud setup enables apps + systemd.services.nextcloud-setup = { + after = [ "nextcloud-oidc-secret-secret.service" ]; + postStart = '' + ${config.services.nextcloud.occ}/bin/nextcloud-occ user_oidc:provider pocket-id \ + --clientid="c8a32c58-a781-4f14-9070-f498fdfda438" \ + --clientsecret-file="${config.secrets.nextcloud-oidc-secret.dest}" \ + --discoveryuri="https://${hostnames.auth}/.well-known/openid-configuration" \ + --scope="openid profile email" \ + --mapping-uid="preferred_username" \ + --unique-uid=0 + ''; + }; + # Grant user access to Nextcloud directories users.users.${username}.extraGroups = [ "nextcloud" ];