ChiefOnboarding
Employee onboarding automation platform. ChiefOnboarding lets HR teams define onboarding sequences for new hires — assigning tasks, collecting documents, sending introductions, and integrating with tools like Slack and Google Workspace. All onboarding data and workflow definitions are stored in PostgreSQL.
Key Features
- Onboarding sequences — ordered tasks, automated triggers, and conditional workflows
- Integrations — Slack, Google Workspace, email notifications, and webhook support
- Multi-role access — admin, manager, and buddy role assignments
- PostgreSQL backend — bundled subchart or external database
- Django application — secure SECRET_KEY management for sessions and CSRF protection
- Ingress support — TLS via cert-manager with configurable ingress class
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install chiefonboarding helmforge/chiefonboarding
OCI registry:
helm install chiefonboarding oci://ghcr.io/helmforgedev/helm/chiefonboarding
Deployment Examples
# values.yaml — ChiefOnboarding with bundled PostgreSQL (default)
chiefonboarding:
baseUrl: 'https://onboarding.example.com'
allowedHosts:
- onboarding.example.com
secretKey: 'a-random-50-char-django-secret-key-here-replace-me'
postgresql:
enabled: true
auth:
password: 'postgres-password'
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: onboarding.example.com
paths:
- path: /
pathType: Prefix# values.yaml — ChiefOnboarding with external PostgreSQL
chiefonboarding:
baseUrl: 'https://onboarding.example.com'
allowedHosts:
- onboarding.example.com
secretKey: 'a-random-50-char-django-secret-key-here-replace-me'
postgresql:
enabled: false
database:
external:
host: postgresql.database.svc
port: '5432'
name: chiefonboarding
username: chiefonboarding
password: 'db-password'
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: onboarding.example.com
paths:
- path: /
pathType: Prefix# values.yaml — Production setup with secrets, TLS, and Slack integration
chiefonboarding:
baseUrl: 'https://onboarding.example.com'
allowedHosts:
- onboarding.example.com
existingSecret: chiefonboarding-secret
existingSecretKey: secret-key
extraEnv:
# Slack integration
- name: SLACK_APP_TOKEN
valueFrom:
secretKeyRef:
name: chiefonboarding-integrations
key: slack-app-token
- name: SLACK_BOT_TOKEN
valueFrom:
secretKeyRef:
name: chiefonboarding-integrations
key: slack-bot-token
postgresql:
enabled: false
database:
external:
host: postgresql.production.svc
port: '5432'
name: chiefonboarding
username: chiefonboarding
existingSecret: chiefonboarding-db-secret
existingSecretPasswordKey: password
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: onboarding.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: chiefonboarding-tls
hosts:
- onboarding.example.com
networkPolicy:
ingressFrom:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-systemConfiguration Reference
Application and Service ports
chiefonboarding.port configures the real Gunicorn listener in the official
Supervisor topology. service.port remains an independent client-facing port
and targets the named application listener:
chiefonboarding:
port: 9080
service:
port: 8080
The chart copies the upstream Supervisor configuration to a writable temporary
file and replaces only its fixed 8000 bind value before startup. The k3d
custom-port scenario performs an HTTP request against the overridden listener.
It also applies idempotent migrations before Supervisor starts, preventing the
upstream Django Q process from querying queue tables while a fresh database is
still being migrated.
Security Scan
Kubescape scan for the chart standards backfill:
| Framework | Score |
|---|---|
| MITRE | 100% |
| NSA | 67.5% |
| SOC2 | 90% |
Production hardening should include stable existing Secrets, explicit CPU and memory requests and limits, TLS ingress, and an explicit ingress-controller peer in the default NetworkPolicy.
Core
| Parameter | Type | Default | Description |
|---|---|---|---|
nameOverride |
string | "" |
Override the chart name. |
fullnameOverride |
string | "" |
Override the full release name. |
commonLabels |
object | {} |
Extra labels added to all resources. |
Image
| Parameter | Type | Default | Description |
|---|---|---|---|
image.repository |
string | docker.io/chiefonboarding/chiefonboarding |
ChiefOnboarding container image. |
image.tag |
string | "v2.5.0" |
Image tag. |
image.digest |
string | pinned SHA-256 | Immutable official image manifest. |
image.pullPolicy |
string | IfNotPresent |
Image pull policy. |
imagePullSecrets |
array | [] |
Pull secrets for private registries. |
ChiefOnboarding Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
chiefonboarding.port |
integer | 8000 |
Actual Gunicorn listener, independent from the Service port. |
chiefonboarding.baseUrl |
string | "" |
Public base URL of the instance (e.g. https://onboarding.example.com). |
chiefonboarding.allowedHosts |
array | local hosts | Django Host-header allowlist; add every public hostname. |
chiefonboarding.secretKey |
string | "" |
Django SECRET_KEY for session signing and CSRF protection. |
chiefonboarding.existingSecret |
string | "" |
Existing Kubernetes Secret containing the Django secret key. |
chiefonboarding.existingSecretKey |
string | secret-key |
Key inside the existing secret holding the Django SECRET_KEY. |
chiefonboarding.extraEnv |
array | [] |
Extra environment variables for integrations and advanced configuration. |
chiefonboarding.baseUrl must be set to your actual public URL before deploying. Django uses this value to generate
links in email notifications and onboarding task messages. Without it, all links sent to new hires will be empty or
incorrect.
When chiefonboarding.secretKey is empty, the chart generates the key once, reuses it with lookup on upgrades, and
retains the Secret on uninstall. Back it up with PostgreSQL. Deliberately changing or deleting it invalidates user
sessions, pending password reset links, and CSRF tokens. An existing Secret is preferred for production.
ChiefOnboarding integrations (Slack, Google Workspace, email) are configured via environment variables. Use
chiefonboarding.extraEnv with secretKeyRef to inject integration tokens securely. See the ChiefOnboarding
integration documentation for the full list of required
variables per integration.
Database — Embedded Subchart
| Parameter | Type | Default | Description |
|---|---|---|---|
postgresql.enabled |
boolean | true |
Deploy a bundled PostgreSQL subchart for ChiefOnboarding. |
postgresql.architecture |
string | standalone |
PostgreSQL deployment architecture. |
postgresql.auth.database |
string | chiefonboarding |
Database name created by the subchart. |
postgresql.auth.username |
string | chiefonboarding |
Database username created by the subchart. |
postgresql.auth.password |
string | "" |
Database password (auto-generated if empty). |
postgresql.auth.existingSecret |
string | "" |
Existing bundled PostgreSQL Secret. |
postgresql.auth.existingSecretUserPasswordKey |
string | user-password |
Application password key. |
Database — External
| Parameter | Type | Default | Description |
|---|---|---|---|
database.external.host |
string | "" |
External PostgreSQL hostname or IP. |
database.external.port |
string | "5432" |
External PostgreSQL port. |
database.external.name |
string | chiefonboarding |
Database name on the external server. |
database.external.username |
string | chiefonboarding |
Username for the external database. |
database.external.password |
string | "" |
Password for the external database (plain text — prefer secret). |
database.external.existingSecret |
string | "" |
Existing secret containing the database password. |
database.external.existingSecretPasswordKey |
string | password |
Key inside the existing secret for the password. |
Service
| Parameter | Type | Default | Description |
|---|---|---|---|
service.type |
string | ClusterIP |
Kubernetes service type. |
service.port |
integer | 80 |
Service port exposed to the cluster. |
service.annotations |
object | {} |
Annotations for the Service. |
Ingress
| Parameter | Type | Default | Description |
|---|---|---|---|
ingress.enabled |
boolean | false |
Enable an Ingress resource. |
ingress.ingressClassName |
string | traefik |
Ingress class name. |
ingress.annotations |
object | {} |
Annotations for the Ingress (e.g. cert-manager). |
ingress.hosts |
array | [] |
Ingress host and path rules. |
ingress.tls |
array | [] |
TLS configuration (secret name and hosts). |
Probes
| Parameter | Type | Default | Description |
|---|---|---|---|
probes.startup.enabled |
boolean | true |
Enable startup probe. |
probes.startup.initialDelaySeconds |
integer | 10 |
Startup probe initial delay. |
probes.startup.periodSeconds |
integer | 5 |
Startup probe period. |
probes.startup.timeoutSeconds |
integer | 3 |
Startup probe timeout. |
probes.startup.failureThreshold |
integer | 30 |
Startup probe failure threshold. |
probes.liveness.enabled |
boolean | true |
Enable liveness probe. |
probes.liveness.initialDelaySeconds |
integer | 0 |
Liveness probe initial delay. |
probes.liveness.periodSeconds |
integer | 15 |
Liveness probe period. |
probes.liveness.timeoutSeconds |
integer | 5 |
Liveness probe timeout. |
probes.liveness.failureThreshold |
integer | 3 |
Liveness probe failure threshold. |
probes.readiness.enabled |
boolean | true |
Enable readiness probe. |
probes.readiness.initialDelaySeconds |
integer | 0 |
Readiness probe initial delay. |
probes.readiness.periodSeconds |
integer | 10 |
Readiness probe period. |
probes.readiness.timeoutSeconds |
integer | 5 |
Readiness probe timeout. |
probes.readiness.failureThreshold |
integer | 3 |
Readiness probe failure threshold. |
Resources and Security
| Parameter | Type | Default | Description |
|---|---|---|---|
resources |
object | {} |
CPU and memory requests and limits. |
podSecurityContext.seccompProfile.type |
string | RuntimeDefault |
Pod seccomp profile. |
securityContext.allowPrivilegeEscalation |
boolean | false |
Prevent privilege escalation. |
securityContext.capabilities.drop |
array | [ALL] |
Dropped Linux capabilities. |
securityContext.runAsNonRoot |
boolean | false |
Upstream root compatibility exception. |
securityContext.readOnlyRootFilesystem |
boolean | false |
Upstream writable-path compatibility exception. |
Service Account
| Parameter | Type | Default | Description |
|---|---|---|---|
serviceAccount.create |
boolean | true |
Create a dedicated ServiceAccount. |
serviceAccount.name |
string | "" |
Override the ServiceAccount name. |
serviceAccount.annotations |
object | {} |
Annotations for the ServiceAccount. |
serviceAccount.automountServiceAccountToken |
boolean | false |
Mount the Kubernetes API token. |
NetworkPolicy
| Parameter | Type | Default | Description |
|---|---|---|---|
networkPolicy.enabled |
boolean | true |
Isolate application ingress. |
networkPolicy.ingressFrom |
array | [] |
Additional peers allowed to reach the HTTP listener. |
The default policy permits pods from the same Helm release. Add the actual ingress-controller namespace and pod selectors when the controller runs elsewhere. Egress stays unrestricted for SMTP, Slack, OIDC, S3, and custom integration destinations. A NetworkPolicy-capable CNI is required.
Scheduling
| Parameter | Type | Default | Description |
|---|---|---|---|
nodeSelector |
object | {} |
Node selector for scheduling. |
tolerations |
array | [] |
Tolerations for scheduling. |
affinity |
object | {} |
Affinity rules. |
topologySpreadConstraints |
array | [] |
Topology spread constraints. |
priorityClassName |
string | "" |
PriorityClass for the pod. |
terminationGracePeriodSeconds |
integer | 30 |
Termination grace period. |
podLabels |
object | {} |
Extra labels for the pod. |
podAnnotations |
object | {} |
Extra annotations for the pod. |
Extra
| Parameter | Type | Default | Description |
|---|---|---|---|
extraVolumes |
array | [] |
Extra volumes to attach to the pod. |
extraVolumeMounts |
array | [] |
Extra volume mounts for the container. |
extraManifests |
array | [] |
Extra Kubernetes manifests deployed alongside the chart. |
Common Issues
Helm cannot observe data-only changes in an externally managed application or database Secret. Restart the ChiefOnboarding Deployment after rotation and verify login, database access, and a background workflow.
If users cannot log in after a Helm upgrade, the Django SECRET_KEY may have changed. Check that
chiefonboarding.secretKey or chiefonboarding.existingSecret is set and matches the value used during the previous
deployment.
ChiefOnboarding does not ship with a default admin account. After the first deployment, access the instance and complete the initial setup wizard to create your admin credentials. The setup wizard is only shown when no admin account exists.
More Information
- ChiefOnboarding Official Website
- ChiefOnboarding Documentation
- ChiefOnboarding GitHub Repository
- HelmForge ChiefOnboarding Chart Source
Upgrading to 2.5.0
Upstream 2.5.0 adds access reports and CSV exports, external user-ID backfill, pagination fixes, and background offboarding account checks. Back up PostgreSQL and preserve the Django secret before upgrading; startup applies the application migrations. Update custom integration manifests for user-ID lookup before using backfill.
Presigned S3 uploads remain the upstream default. The optional
AWS_USE_PRESIGNED_UPLOADS=False environment variable routes uploads through the
server; account for proxy timeouts and upload limits. AWS_CDN_URL optionally
sets the download URL base. Configure these through
chiefonboarding.extraEnv, with S3 credentials from Secrets. Existing ports,
database configuration and deployment topology are unchanged.