Registry Helm Chart 4.x
Overview
The OpenG2P Registry Helm Chart (openg2p-registry) is a comprehensive Kubernetes deployment package that installs the Registry module along with all its required services. Chart version 4.x is designed for the Gen2 architecture of the Registry.
This guide assumes that the Kubernetes infrastructure and the commons environment have already been set up as described in the Deployment Instructions and Automation guides. The commons release provides shared services such as PostgreSQL, Keycloak, MinIO, IAM, and Keymanager that the Registry chart depends on.
Versions
4.1.0-develop
In progress
Same as 4.0.0.
Commons Services 2.0.1 IAM Service 1.0.0 ID Generator 1.0.0 Master Data 0.0.0-develop
In progress.
Switched intra-cluster service-to-service calls to internal Kubernetes service DNS for ID Generator, MinIO, and Staff Portal API (no longer routed through ingress).
08 May 2026
Same as 4.0.0.
Commons Services 2.0.1 IAM Service 1.0.0 ID Generator 1.0.0 Master Data 0.0.0-develop
Audit manager connection added
Uninstall script added.
21 Apr 2026
farmer-registry-staff-portal-api:v1.0.2 farmer-registry-partner-api:v1.0.2 farmer-registry-celery:v1.0.2 (the same celery image is used as a beat-producer as well as a worker - based on an input parameter) registry-staff-portal-ui:v1.0.2
Commons Base 2.0.0 Commons Services 2.0.0 IAM Service 1.0.0 ID Generator 1.0.0 Master Data 0.0.0-develop
Stable Version
Components
The chart deploys the following application components and subcharts:
Staff Portal API
Application
Enabled
Backend API for the staff-facing registry portal
Staff Portal UI
Application
Enabled
Next.js frontend for registry staff operations
Partner API
Application
Enabled
API for partner/external system integrations
Beneficiary Portal API
Application
Disabled
API for beneficiary self-service portal
Celery Beat Producer
Application
Enabled
Periodic task scheduler for async processing
Celery Worker
Application
Enabled
Worker for background tasks (ingestion, deduplication, etc.)
Redis
Subchart
Enabled
Message broker and result backend for Celery
postgres-init
Subchart
Enabled
Initialises the registry database, user, and extensions in the shared PostgreSQL
ID Generator
Subchart
Enabled
Generates unique IDs for registrants and households
Keycloak Init
Subchart
Enabled
Creates the OIDC client and RBAC roles in Keycloak
Meta Data Seeding
Hook Job
Enabled
Seeds mandatory configuration and optional sample data into the database
Architecture diagram
Prerequisites
Before installing the Registry chart, ensure the following are available in the target namespace:
PostgreSQL
commons release
Shared database server. The postgres superuser secret must exist as commons-postgresql.
Keycloak
commons release
Namespace-local Keycloak at keycloak.<namespace>.openg2p.org. Admin secret must exist as commons-keycloak.
MinIO
commons release
Object storage for document templates. Secret: commons-minio.
IAM Service
commons release
Authentication provider at http://commons-services-iam-staff-portal-api.
Keymanager
commons release
Key management service at commons-services-keymanager.
Master Data API
commons release
Reference/master data service at http://commons-services-master-data-api.
Istio
Infrastructure
Service mesh with ingress gateway for routing.
Fluent Operator
Infrastructure
Fluent Operator + Fluentbit DaemonSet for log collection. OpenSearch Output created by commons-base.
Wildcard DNS
Infrastructure
*.<namespace>.openg2p.org resolving to the cluster ingress.
The commons release name is assumed to be commons throughout the chart defaults. If your commons release has a different name, you must override the relevant service URLs (keycloak-init.keycloak.url, keycloak-init.keycloak.existingSecret, global.iamServiceUrl, global.keymanagerInstallationName, etc.).
Installation
Using Rancher (recommended)
Navigate to Apps > Charts in the Rancher UI for your cluster.
Select the OpenG2P Registry chart from the
openg2pcatalogue.Choose the target namespace (e.g.
trial,qa,production).Set the release name (e.g.
farmer-registry). This name is used to derive hostnames, database names, and Kubernetes resource names.Fill in the configuration form (see Configuration below). For advanced options, switch to Edit YAML.
Under Helm Options, disable the
waitflag to avoid timeouts on first install.Click Install and wait for all pods to reach
Runningstate.
Using Helm CLI
Example:
To upgrade an existing release:
To perform a dry-run and inspect the rendered manifests:
Configuration
Hostname and domain conventions
The chart uses Go template expressions in values.yaml to derive hostnames automatically from the Helm release name and namespace:
Service
Default hostname pattern
Example (farmer-registry in trial)
Staff Portal UI
<release>.<namespace>.openg2p.org
farmer-registry.trial.openg2p.org
Staff Portal API
staff-<release>.<namespace>.openg2p.org
staff-farmer-registry.trial.openg2p.org
Partner API
partner-<release>.<namespace>.openg2p.org
partner-farmer-registry.trial.openg2p.org
ID Generator
idgenerator-<release>.<namespace>.openg2p.org
idgenerator-farmer-registry.trial.openg2p.org
Keycloak
keycloak.<namespace>.openg2p.org
keycloak.trial.openg2p.org
The base hostname is controlled by global.registryHostname.
Global parameters
These parameters are shared across all components:
global.registryVariant
farmer
Registry variant name. Affects Docker image names.
global.registryHostname
{{ .Release.Name }}.{{ .Release.Namespace }}.openg2p.org
Base hostname for all services.
global.postgresqlHost
commons-postgresql
PostgreSQL server hostname.
global.keycloakBaseUrl
https://keycloak.{{ .Release.Namespace }}.openg2p.org
Keycloak base URL.
global.keycloakRealm
staff-{{ .Release.Namespace }}
Keycloak realm name for staff authentication.
global.authClientId
registry-staff-portal
OIDC client ID in Keycloak.
global.authClientSecret
registry-staff-portal
K8s Secret name holding the OIDC client password.
global.iamServiceUrl
http://commons-services-iam-staff-portal-api
Internal URL of the IAM service.
global.masterDataApiUrl
http://commons-services-master-data-api
Internal URL of the Master Data API.
global.keymanagerInstallationName
commons-services-keymanager
Internal service name for keymanager.
Rancher UI questions
The chart provides a simplified Rancher UI form (questions.yaml) with the most commonly configured parameters:
Registry Hostname
global.registryHostname
General
PostgreSQL Server Host
global.postgresqlHost
General
Keycloak Base URL
global.keycloakBaseUrl
General
Keycloak Init toggle
keycloak-init.enabled
General
Staff Portal API toggle
staffPortalApi.enabled
General
Staff Portal UI toggle
staffPortalUi.enabled
General
Partner API toggle
partnerApi.enabled
General
Beneficiary Portal API toggle
benePortalApi.enabled
General
ID Generator toggle
idgenerator.enabled
General
ID Types Configuration
(see note)
ID Generator
Enable Logging
logging.enabled
Logging
Fluent Output Name
logging.outputRef
Logging
ID type configuration (types, lengths, pool settings) cannot be expressed as simple form fields. The Rancher UI shows a note directing users to switch to Edit YAML to modify the idgenerator.idGenerator.appConfig.idTypes section.
Database configuration
The chart automatically derives database names and user names from the release name to avoid collisions:
Registry
<release_name> (hyphens replaced with underscores)
<release_name>_user
ID Generator
<release_name>_idgenerator
<release_name>_idgenerator_user
For example, release farmer-registry creates databases farmer_registry and farmer_registry_idgenerator.
The postgres-init subchart handles database and user creation automatically. It generates a random password, stores it in a Kubernetes Secret, and creates the database/user in PostgreSQL.
The postgres-init chart uses the Helm lookup function to check if the DB user secret already exists. If it does, the secret is not overwritten -- the existing password is preserved. The secret is annotated with helm.sh/resource-policy: keep so it survives Helm uninstalls.
Keycloak and OIDC
The keycloak-init subchart creates:
The Keycloak realm (e.g.
staff)An OIDC client (
registry-staff-portal) with a randomly generated secretRBAC roles on the client (see below)
A default admin user with initial credentials and client role assignments
The Keycloak Init Job connects to the namespace-local Keycloak using the admin credentials from the commons-keycloak secret.
Default RBAC roles created:
Operations
Intake Officer, Intake Validator, Data Editor, Data Validator, Data Supervisor, Integration Manager, Operations Administrator
Configuration
Schema Designer, Integration Specialist, Reference Data Specialist, Technical Administrator
See RBAC Roles and Permissions for detailed role descriptions.
Default user created:
The chart creates an initial admin user in the staff realm with the following defaults:
Username
admin
Password
admin
Client role mappings
Operations Administrator, Technical Administrator (on registry-staff-portal client)
Change the default admin password immediately after first login. To customise the default user or add more users, override keycloak-init.realms.staff.users in your values file.
User definition structure:
Keycloak-init parameters:
keycloak-init.enabled
true
Enable/disable Keycloak client creation.
keycloak-init.keycloak.url
http://commons-keycloak:80
Internal Keycloak URL.
keycloak-init.keycloak.user
admin
Keycloak admin username.
keycloak-init.keycloak.existingSecret
commons-keycloak
K8s Secret containing the admin password.
keycloak-init.keycloak.existingSecretKey
admin-password
Key within the secret.
ID Generator
The ID Generator subchart (idgenerator) provides unique ID generation for registrants. Configuration is under idgenerator.idGenerator.appConfig:
idTypes
farmer_id (12), household_id (10)
Map of ID type names to their configuration.
poolMinThreshold
1000
Minimum IDs in pool before regeneration triggers.
poolGenerationBatchSize
5000
Number of IDs generated per batch.
poolCheckIntervalSeconds
30
How often the pool level is checked.
Logging
The chart ships a Fluent Operator Flow resource that captures JSON logs from all OpenG2P application pods and routes them to the OpenSearch Output already created by the commons-base chart. Logging is enabled by default.
How it works:
The
Flowmatches pods byapp.kubernetes.io/instance(the Helm release name) and an explicit list of container names, so init containers (e.g.postgres-checker) are excluded.A
parserfilter parses the JSON log lines emitted by all OpenG2P services.A
tag_normaliserfilter formats the Fluent tag as<namespace>.<pod>.<container>for consistent OpenSearch indexing.Logs are forwarded to the namespace-scoped Output (default:
commons-opensearch) vialocalOutputRefs.
The Fluent Operator and Fluentbit DaemonSet must already be running on the cluster (typically deployed as part of the Rancher/infrastructure layer). The chart only creates the Flow resource — it does not deploy Fluentbit itself.
Logging parameters:
logging.enabled
true
Enable/disable the Fluent Operator Flow resource.
logging.outputRef
commons-opensearch
Name of the namespace-scoped Fluent Output resource (from commons-base).
logging.containerNames
(see below)
List of container names whose logs are captured.
Default containerNames:
These must match the nameOverride values of the corresponding components. If you add custom sidecar containers or change a component's nameOverride, update this list accordingly.
Audit Manager integration
Available from chart 4.1.0 with staff-portal-api 1.1.x. Earlier chart/image versions ignore the env vars (no harm in leaving them configured).
The chart wires three env vars into staff-portal-api so that every authenticated API call — and every rejected anonymous attempt — emits a CloudEvent to the OpenG2P Audit Manager. Emission is fire-and-forget; the audit pipeline cannot delay or fail a user request.
Parameters:
global.auditEnabled
false
Master switch. Must be true AND auditManagerUrl must be set for any audits to flow.
global.auditManagerUrl
http://audit-manager:80
Internal URL of the Audit Manager service. Default uses the short Kubernetes DNS name (works when audit-manager is in the same namespace as the registry).
global.auditAnonymousFailures
true
When true, also audit rejected anonymous calls (401/403). Set false to skip them and audit only authenticated user calls.
Enabling for an environment:
Cross-namespace deployment. If audit-manager is in a different namespace than the registry, use the FQDN:
What gets audited. Every authenticated POST to staff-portal-api endpoints (/registry-config/*, /register-metadata/*, /change-requests/*, /ingestion-config/*, /outgestion-config/*, etc.) plus rejected anonymous attempts. Health probes (/ping), OpenAPI surfaces (/docs, /redoc, /openapi.json), and OPTIONS preflight are always skipped.
For the full schema, query examples, and middleware design, see the audit-manager Integration with Registry section.
Disabling. Set global.auditEnabled=false (or omit auditManagerUrl). The middleware becomes a no-op — no per-pod restart logic needed beyond the standard helm upgrade.
Meta Data Seeding
After all application pods are running, the chart seeds mandatory configuration meta data (register definitions, lookup data, VC configurations, etc.) into the database. Sample/demo data can optionally be loaded as well.
For full details on what gets seeded, the extensions repository structure, and the Docker image lifecycle, see Meta Data Seeding.
The seeding runs as a Helm post-install / post-upgrade hook Job. Two init containers ensure readiness before execution:
wait-for-db — polls PostgreSQL until the database is reachable
wait-for-apps — polls each enabled API service (e.g.
/ping) to confirm tables have been created
Parameters:
dbSeed.enabled
true
Enable/disable the seed Job.
dbSeed.loadSampleData
false
Also load sample/demo data (off by default).
dbSeed.image.repository
openg2p/openg2p-farmer-registry-db-seed
Docker image containing the seed SQL scripts.
dbSeed.image.tag
develop
Image tag (typically matches the extensions branch).
To deploy a different registry variant (e.g. family), override dbSeed.image.repository with the corresponding seed image (e.g. openg2p/openg2p-family-registry-db-seed).
Component toggles
Each application component can be individually enabled or disabled:
Key concepts and notes
Template-driven defaults
Many values in values.yaml use Go template expressions (e.g. {{ .Release.Name }}, {{ .Release.Namespace }}). These are resolved at install time, making the chart portable across different release names and namespaces without manual edits.
When a value contains a template that is referenced by another template, the chart uses the tpl function to ensure nested resolution. For example:
Secret lifecycle
The chart involves two distinct secret flows:
Database secrets -- Created by
postgres-initusing Helm'slookupfunction. If the secret already exists, it is preserved. Annotated withhelm.sh/resource-policy: keepto survive uninstalls.OIDC client secret -- Created by
keycloak-init'sclient-secrets.yamltemplate with a random password. The Keycloak Init Job reads this secret and pushes it to Keycloak when creating the OIDC client.
If you uninstall and reinstall the chart, the database may retain the old password while a new secret is generated. Ensure secrets are not manually deleted between installs if the databases persist.
Subchart isolation
The ID Generator runs its own postgres-init instance for its database. To avoid Kubernetes resource name collisions with the parent chart's postgres-init, the subchart uses nameOverride: idgen-pg-init. This keeps ServiceAccount and Job names unique and within the Kubernetes 63-character label limit.
Shared commons services
The chart references several services from the commons release by their internal Kubernetes service names:
PostgreSQL
commons-postgresql
Keycloak
commons-keycloak:80
MinIO
minio.<namespace>.openg2p.org
IAM
commons-services-iam-staff-portal-api
Keymanager
commons-services-keymanager
Master Data API
commons-services-master-data-api
These names assume the commons release is named commons. Override the corresponding global parameters if your commons release uses a different name.
Troubleshooting
Secret ownership conflict on install
This occurs when a Kubernetes Secret already exists and is owned by a different Helm release. Common causes:
The
keycloak-initsubchart's default realm configuration includes clients (e.g.openg2p-superset) that are already created by the commons release. Override thekeycloak-init.realmssection to include only the registry-specific realm and clients.The
authClientSecretname collides with another registry release in the same namespace. See the note on multiple releases below.
Keycloak Init Job fails with CreateContainerConfigError
CreateContainerConfigErrorThe Job cannot find the Keycloak admin secret. Ensure:
The commons release is installed and the
commons-keycloaksecret exists in the namespace.If your commons release name differs, update
keycloak-init.keycloak.existingSecretaccordingly.
IAM Invalid Login Provider Id
Invalid Login Provider IdThe LOGIN_PROVIDER_ID in the Staff Portal UI must match a configured login provider in the IAM service database. The default value 4 may not exist in your environment. Check the IAM service's login provider configuration and update the value in staffPortalUi.envVars.LOGIN_PROVIDER_ID.
Database password mismatch after reinstall
If the chart is uninstalled and the DB user secret is deleted manually, but the database user persists in PostgreSQL with the old password, a fresh install will generate a new random password that does not match. To resolve:
Delete the database user from PostgreSQL before reinstalling, or
Recreate the secret with the correct password before installing.
Installing multiple releases
The chart can be installed multiple times in the same namespace with different release names (e.g. farmer-registry and livestock-registry). Most resource names are derived from {{ .Release.Name }} and will not collide. However, the following values are currently hardcoded and will clash:
global.authClientId
registry-staff-portal
Both releases create the same Keycloak client
global.authClientSecret
registry-staff-portal
Both releases try to own the same K8s Secret
keycloak-init clientId
registry-staff-portal
Duplicate client in Keycloak
When installing multiple registry releases in the same namespace, you must override global.authClientId, global.authClientSecret, and the keycloak-init.realms clientId to be unique per release (e.g. farmer-registry-staff-portal).
Maintaining multiple variants (wrapper chart strategy)
This section captures the recommended approach for maintaining multiple domain variants of the Registry (farmer, family, NSR, livestock, etc.) without duplicating the base chart. It is intended as a handover note for teams spinning up new variants.
Problem
OpenG2P Registry Gen 2 is one base Helm chart with many domain variants. Variants differ only by:
Docker image names (every component has a variant-branded image)
ID Generator
appConfig.idTypesOptionally a variant-specific meta-data seed image
We want each variant to be an independently versioned package, not a copy-paste of the base chart.
Approach: wrapper charts in separate repos
The base chart stays in openg2p-registry-gen2-deployment. Each variant gets its own repo holding a thin wrapper chart that depends on the base chart by version. This preserves the existing "branch name == chart version" convention per repo.
Wrapper repo contents
Chart.yaml:
values.yaml — overrides must be nested under the base chart name; global.* values go at the top level:
CI and publishing
All variants publish to the same Helm repository: https://openg2p.github.io/openg2p-helm. Each wrapper repo uses the same publish-trigger.yml workflow as the base repo. On push of a branch/tag, CI runs:
helm dep up— pulls the pinned base chart tarball from the published Helm repo.helm package— producesopeng2p-<variant>-registry-<version>.tgz.Commits the tarball to
openg2p/openg2p-helm gh-pages.
Versioning rules
Variant-only change (new image tag, new ID type)
Wrapper MINOR/PATCH only
Base chart backward-compatible change
Base MINOR; wrappers opt in when ready
Base chart breaking change
Base MAJOR; wrappers bump MAJOR on adoption
Boilerplate mitigations
Create a GitHub template repo (e.g.
openg2p-registry-variant-template) so spinning up a new variant repo is a 5-minute operation.Ship a uniform
scripts/bump-base.shin every wrapper for one-command base-version bumps.Use Renovate or Dependabot to auto-PR base-version bumps across variant repos when the base releases.
Rejected alternatives
Single chart with
values-<variant>.yaml— no per-variant chart versioning.if .Values.variant == "nsr"branches inside base templates — anti-pattern; variant knowledge leaks into the base.Wrapper charts inside the base repo — couples variant release cadence to base-repo branching.
Mono-repo with per-chart tags — breaks the branch-name-equals-version convention.
Next steps for a new variant (example: NSR)
Create the template repo (one-time).
Spin up
openg2p-nsr-registry-deploymentfrom the template.Decide Docker image names; publish component images under
openg2p/openg2p-nsr-registry-*.Define the variant's ID types for the ID Generator.
Decide the seed strategy — add
openg2p-registry-nsr-extension/under openg2p-registry-gen2-extensions, or skip seed for v1.Set Rancher branding (
catalog.cattle.io/display-name, icon,questions.yaml).First wrapper release:
openg2p-nsr-registry:1.0.0depends onopeng2p-registry:4.0.0.
Related references
Base chart repo: openg2p-registry-gen2-deployment
Published Helm repo:
https://openg2p.github.io/openg2p-helm(gh-pages of openg2p/openg2p-helm)Variant meta-data seed SQL: openg2p-registry-gen2-extensions — one
openg2p-registry-<variant>-extension/folder per variant
Source code and references
Chart source: openg2p-registry-gen2-deployment
Helm repository:
https://openg2p.github.io/openg2p-helmRBAC documentation: RBAC Roles and Permissions
Commons chart: OpenG2P Commons Helm Chart
Last updated
Was this helpful?