diff --git a/doc/release-notes/rl-2605.section.md b/doc/release-notes/rl-2605.section.md index ef3ea580eb25..0d999f37a294 100644 --- a/doc/release-notes/rl-2605.section.md +++ b/doc/release-notes/rl-2605.section.md @@ -94,6 +94,8 @@ - If you previously used `configFile`, migrate your configuration to the `settings` option and extract the private key to a separate file referenced by `PrivateKeyPath`. - If you previously used `persistentKeys`, convert your keys to PEM format and store them in a secure location accessible only to root, then reference them via `PrivateKeyPath`. +- `pocket-id` has been updated to version 2 that contains [breaking changes](https://pocket-id.org/docs/setup/major-releases/migrate-v2). + - `asio` (standalone version of `boost::asio`) has been updated from 1.24.0 to 1.36.0. Some breaking changes were introduced between these two versions, and the one affected most was the removal of `asio::io_service` in favor of `asio::io_context` in 1.33.0. `asio_1_32_0` is retained for packages that have not completed migration. `asio_1_10` has been removed as no packages depend on it anymore. diff --git a/nixos/modules/services/security/pocket-id.nix b/nixos/modules/services/security/pocket-id.nix index 728756c0d77e..65f9468f7e7e 100644 --- a/nixos/modules/services/security/pocket-id.nix +++ b/nixos/modules/services/security/pocket-id.nix @@ -19,6 +19,7 @@ let optionalAttrs ; inherit (lib.types) + attrsOf bool path str @@ -29,6 +30,10 @@ let format = pkgs.formats.keyValue { }; settingsFile = format.generate "pocket-id-env-vars" cfg.settings; + + exportCredentials = n: _: ''export ${n}="$(${pkgs.systemd}/bin/systemd-creds cat ${n}_FILE)"''; + exportAllCredentials = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList exportCredentials vars); + getLoadCredentialList = lib.mapAttrsToList (n: v: "${n}_FILE:${v}") cfg.credentials; in { meta.maintainers = with maintainers; [ @@ -44,17 +49,36 @@ in environmentFile = mkOption { type = path; description = '' - Path to an environment file loaded for the Pocket ID service. - + Path to an environment file to be loaded. This can be used to securely store tokens and secrets outside of the world-readable Nix store. + See [PocketID environment variables](https://pocket-id.org/docs/configuration/environment-variables). + Example contents of the file: MAXMIND_LICENSE_KEY=your-license-key + + Alternatively you can use `services.pocket-id.credentials` to define each variable in separate files. ''; default = "/dev/null"; example = "/var/lib/secrets/pocket-id"; }; + credentials = mkOption { + type = attrsOf path; + default = { }; + example = { + ENCRYPTION_KEY = "/run/secrets/pocket-id/encryption-key"; + }; + description = '' + Environment variables which are loaded from the contents of the specified file paths. + This can be used to securely store tokens and secrets outside of the world-readable Nix store. + + See [PocketID environment variables](https://pocket-id.org/docs/configuration/environment-variables). + + Alternatively you can use `services.pocket-id.environmentFile` to define all the variables in a single file. + ''; + }; + settings = mkOption { type = submodule { freeformType = format.type; @@ -81,7 +105,7 @@ in description = '' Whether to disable analytics. - See [docs page](https://pocket-id.org/docs/configuration/analytics/). + See the [analytics documentation](https://pocket-id.org/docs/configuration/analytics/). ''; default = false; }; @@ -91,9 +115,9 @@ in default = { }; description = '' - Environment variables that will be passed to Pocket ID, see - [configuration options](https://pocket-id.org/docs/configuration/environment-variables) - for supported values. + Environment variables to be passed. + + See [PocketID environment variables](https://pocket-id.org/docs/configuration/environment-variables). ''; }; @@ -101,7 +125,7 @@ in type = path; default = "/var/lib/pocket-id"; description = '' - The directory where Pocket ID will store its data, such as the database. + The directory where Pocket ID will store its data, such as the database when using SQLite. ''; }; @@ -119,29 +143,60 @@ in }; config = mkIf cfg.enable { + assertions = ( + map + ( + # Converted to assert 2026-01-08 + setting: { + assertion = !(cfg.settings ? "${setting}"); + message = '' + `services.pocket-id.settings.${setting}` is deprecated. + See [v1 migration guide](https://pocket-id.org/docs/setup/major-releases/migrate-v1). + ''; + }) + [ + "PUBLIC_APP_URL" + "PUBLIC_UI_CONFIG_DISABLED" + "CADDY_DISABLED" + "CADDY_PORT" + "BACKEND_PORT" + "POSTGRES_CONNECTION_STRING" + "SQLITE_DB_PATH" + "INTERNAL_BACKEND_URL" + ] + ); + warnings = - optional (cfg.settings ? MAXMIND_LICENSE_KEY) - "config.services.pocket-id.settings.MAXMIND_LICENSE_KEY will be stored as plaintext in the Nix store. Use config.services.pocket-id.environmentFile instead." - ++ - concatMap - ( - # Added 2025-05-27 - setting: - optional (cfg.settings ? "${setting}") '' - config.services.pocket-id.settings.${setting} is deprecated. - See https://pocket-id.org/docs/setup/migrate-to-v1/ for migration instructions. - '' - ) - [ - "PUBLIC_APP_URL" - "PUBLIC_UI_CONFIG_DISABLED" - "CADDY_DISABLED" - "CADDY_PORT" - "BACKEND_PORT" - "POSTGRES_CONNECTION_STRING" - "SQLITE_DB_PATH" - "INTERNAL_BACKEND_URL" - ]; + (concatMap + ( + setting: + optional (cfg.settings ? "${setting}") '' + `services.pocket-id.settings.${setting}` will be stored as plaintext in the Nix store. Use `services.pocket-id.credentials.${setting}` or `services.pocket-id.environmentFile` instead. + '' + ) + [ + "ENCRYPTION_KEY" + "MAXMIND_LICENSE_KEY" + "SMTP_PASSWORD" + "LDAP_BIND_PASSWORD" + ] + ) + ++ (concatMap + ( + # Added 2026-01-08 + setting: + optional (cfg.settings ? "${setting}") '' + `services.pocket-id.settings.${setting}` is deprecated. + See [v2 migration guide](https://pocket-id.org/docs/setup/major-releases/migrate-v2). + '' + ) + [ + "DB_PROVIDER" + "KEYS_PATH" + "KEYS_STORAGE" + "LDAP_ATTRIBUTE_ADMIN_GROUP" + ] + ); systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0755 ${cfg.user} ${cfg.group}" @@ -163,12 +218,16 @@ in User = cfg.user; Group = cfg.group; WorkingDirectory = cfg.dataDir; - ExecStart = getExe cfg.package; + ExecStart = pkgs.writeShellScript "pocket-id-start" '' + ${exportAllCredentials cfg.credentials} + ${getExe cfg.package} + ''; Restart = "always"; EnvironmentFile = [ cfg.environmentFile settingsFile ]; + LoadCredential = getLoadCredentialList; # Hardening AmbientCapabilities = ""; diff --git a/nixos/tests/pocket-id.nix b/nixos/tests/pocket-id.nix index 7f2a4a8255f8..d79866882c17 100644 --- a/nixos/tests/pocket-id.nix +++ b/nixos/tests/pocket-id.nix @@ -1,5 +1,9 @@ -{ lib, ... }: +{ pkgs, lib, ... }: +let + # !!! Don't do this with real keys. The /nix store is world-readable! + ENCRYPTION_KEY = pkgs.writeText "pocket-id-encryption-key" "SUeAyRRFZ1uf03ClOE+o++BVENSE/Ptb9YFRF2Sk+zM="; +in { name = "pocket-id"; meta.maintainers = with lib.maintainers; [ @@ -16,6 +20,9 @@ settings = { PORT = 10001; }; + credentials = { + inherit ENCRYPTION_KEY; + }; }; }; @@ -29,9 +36,11 @@ enable = true; settings = { PORT = 10001; - DB_PROVIDER = "postgres"; DB_CONNECTION_STRING = "host=/run/postgresql user=${username} database=${username}"; }; + credentials = { + inherit ENCRYPTION_KEY; + }; }; services.postgresql = { diff --git a/pkgs/by-name/po/pocket-id/package.nix b/pkgs/by-name/po/pocket-id/package.nix index 79db3ac2f2fe..92c4a2847f47 100644 --- a/pkgs/by-name/po/pocket-id/package.nix +++ b/pkgs/by-name/po/pocket-id/package.nix @@ -12,18 +12,18 @@ }: buildGo125Module (finalAttrs: { pname = "pocket-id"; - version = "1.16.0"; + version = "2.1.0"; src = fetchFromGitHub { owner = "pocket-id"; repo = "pocket-id"; tag = "v${finalAttrs.version}"; - hash = "sha256-2tGd/gl0Pm5b5GfkTsChvZoWov4dwljwqDcitX5NKCY="; + hash = "sha256-tBjo5evQVRG0oembk1VfAfM3M/FJ4zPWV/9vgAWH9Kc="; }; sourceRoot = "${finalAttrs.src.name}/backend"; - vendorHash = "sha256-ttbiuYRWbn8KRZtg499R4NF/E9+B+fOylxZcMwNg69M="; + vendorHash = "sha256-hMhOG/2xnI/adjg8CnA0tRBD8/OFDsTloFXC8iwxlV0="; env.CGO_ENABLED = 0; ldflags = [ @@ -56,8 +56,8 @@ buildGo125Module (finalAttrs: { pnpmDeps = fetchPnpmDeps { inherit (finalAttrs) pname version src; pnpm = pnpm_10; - fetcherVersion = 1; - hash = "sha256-drXGcUHP7J7keGra7/x1tr9Pfh/wjzmtUE1yAybYXLQ="; + fetcherVersion = 3; + hash = "sha256-jhlHrekVk0sNLwo8LFQY6bgX9Ic0xbczM6UTzmZTnPI="; }; env.BUILD_OUTPUT_PATH = "dist";