A Kubernetes operator for managing Pocket-ID instances and resources. It deploys a Pocket-ID Deployment or Statefulset and keeps users, user groups, and OIDC clients in sync with your cluster state.
This project is not affiliated with Pocket-ID. It is a community-driven project that aims to provide a Kubernetes operator for managing Pocket-ID instances and related resources.
This project is my first time developing for Kubernetes, writing Go, and using AI coding agents. Large chunks of the codebase are generated by AI. I am not a fan of it but in reality this project would have never been completed in a reasonable timeframe without the help of ai. That said, I would never share something I don't understand and I have done my absolute best to audit it all, but there's bound to be some stray lines and logic errors. If this is a non-starter for using the project I absolutely understand. As I get more comfortable with Go and k8s development I will continue to go through the codebase and clean it up. Any contributions, suggestions, or feedback are greatly appreciated!!
PocketIDInstancePocketIDUserPocketIDUserGroupPocketIDOIDCClient
Start here for detailed configuration guides:
docs/README.mddocs/pocketidinstance.mddocs/pocketiduser.mddocs/pocketidusergroup.mddocs/pocketidoidcclient.mddocs/annotations.md
It's recommended to install this operator via the helm chart.
helm install pocket-id-operator oci://ghcr.io/aclerici38/charts/pocket-id-operator:0.14.3 --set instance.spec.encryptionKey.value="secure16+characterKey"
There will also be a generated manifest to install without helm attached to each release.
For now, this project does not match the release cadence of upstream Pocket-id. Features and bug fixes will be released as time permits which is likely within 24 hours of being merged. The operator is mostly feature-complete with Pocket-id and does not benefit from frequent updates anymore. This may obviously change in the future.
Each new release of Pocket-id is run through all tests against the latest release and current codebase. In addition, I will always run updates in my own k8s cluster immediately to confirm there are no errors that get by the tests. I feel this is adequate testing against upstream updates and allows the operator versioning to be decoupled from upstream.
Therefore, to use an up-to-date version of Pocket-id with this operator it is recommended to manage the upstream pocket-id version separately (instance.spec.image). The version the operator comes bundled with may be behind the latest upstream release. To ensure stability, you can wait several days before updating as I will be sure to release any fixes necessary ASAP.
If you have an issue with this or wuld like to suggest a different approach, feel free to ping me (@aclerici38) in a discussion or issue
This operator supports Pocket-id >=v2.14.0, <v3.0.0.
If an instance reports a version outside that range, the operator logs the detected version and exits, which crash loops the pod rather than issuing calls against an unsupported API. To run Pocket-id <v2.14.0, use a version <=v0.13.1 of the operator.
Tooling and Git hooks are managed by mise (.mise.toml);
run mise install once to set both up (it installs the toolchain and registers
the lefthook hooks described under
Contributing).
Install CRDs and deploy the controller:
mise run install
IMG=<registry>/pocket-id-operator:tag mise run deployRun mise tasks for available tasks. See the docs in docs/ for CRD usage and
examples.
CI runs these checks on every pull request, you can use them to validate locally
mise run lint # golangci-lint
mise run test # regenerate, fmt, vet, then unit tests
mise run test-e2e # full suite against a local Kind cluster (needs Docker)CRDs, DeepCopy methods, dist/install.yaml, dist/crds.yaml, the chart's CRDs,
and the JSON schemas are all derived from the Go API types in api/ and must be
committed and current. Regenerate everything with one task:
mise run regenThe lefthook hooks installed by mise install mostly handle this for you:
- pre-commit — formats staged Go files.
- pre-push — runs
mise run verify-generatedand blocks the push if any derived file is out of date. - post-merge / post-rewrite — re-run
mise run regenafter a pull or rebase, so merged-in API changes never leave stale generated files behind.
CI enforces the same check: if generated files are out of date, the
Regenerate Manifests workflow fails with the command to run. To skip the hooks append --no-verify to the git command.
Every generated file is derived from api/, so never hand-merge a conflict in
one — resolve the source and regenerate:
-
Resolve any conflicts in the API types themselves (
api/**/*_types.go) by hand. These are the only real conflicts. -
Regenerate the derived files — this overwrites the conflict markers left in the CRDs, schemas,
install.yaml, DeepCopy, etc. with correct output:mise run regen git add -A git rebase --continue # or git commit when merging
If any features are added or functionality is changed, documentation in docs/ should be updated.
- Pocket-ID - Obviously, Amazing IDP this project is made for
- Kubebuilder - Excellent framework for building Kubernetes controllers
Copyright 2026.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.