Overview
PocketBase is an open-source backend (MIT licensed) that ships as a single executable: an embedded SQLite database, an auto-generated REST API over your collections, user authentication, file uploads, realtime subscriptions over Server-Sent Events, and a web admin dashboard. This template deploys one stateful PocketBase workload with its data directory on a persistent volume, served over HTTPS on the canonical*.cpln.app endpoint. The superuser account is created from a secret you provide before the server starts listening, so the dashboard never has an unclaimed admin account.
It suits a mobile or single-page app backend, a prototype that needs a real API quickly, or a small internal tool — anywhere a full database plus API server plus auth service would be more than the team needs.
What Gets Created
Prerequisites
One dictionary secret must exist before you install. It holds the superuser login and the key that encrypts settings at rest; none of these values pass through Helm values. Secrets are org-level, so no GVC flag is involved.Create the credentials secret
openssl rand -hex 16 produces exactly the 32 characters PocketBase requires. Set credentials.secretName to this name. If you run more than one release in the same org, give each its own secret.Keep a copy of the encryption key
encryptionKey somewhere safe outside Control Plane. It can never be changed after install without orphaning everything it protects. Read it back any time with:Installation
Once the credentials secret exists, install from the marketplace registry, naming the secret:UI
CLI
Terraform
Pulumi
Configuration
PocketBase Instance
resources block exposes both a reservation and a limit, so the limit is named maxCpu / maxMemory; a values file carrying the bare cpu or memory keys is rejected at render with a message telling you to rename them. Volume capacity is fixed when the volume set is created, so size volumeset.capacity at install time — uploads and PocketBase’s local backup archives share it with the database.
No official PocketBase image exists. This template pins a widely used community build and replaces its entrypoint: the container runs pocketbase superuser upsert to completion and then exec pocketbase serve directly, so the chart depends only on the pocketbase binary at the pinned tag.
Credentials
credentials.secretName names your pre-created dictionary secret holding email, password, and encryptionKey (see Prerequisites). It must exist before you install, and it is the only secret the workload’s identity can reveal. The secret is re-read only when the replica starts, so a changed value needs a forced redeployment — see Rotating the Superuser Password.
Backup
backup.enabled: false removes the schedule only; backup.retention still applies, and a final snapshot is taken when the release is uninstalled either way. See Backing Up.
API
cors.allowedOrigins is passed to PocketBase as its --origins flag and must list at least one origin (the chart refuses to render an empty list). With a restricted list, a browser request from an origin that is not on it still returns 200 but without an access-control-allow-origin header — the browser is what blocks the response. A change takes effect once the new replica is serving, so verify it with a real request rather than by polling readiness.
Access
publicAccess.enabled: false, external requests are refused and you reach the dashboard through a port-forward — see Connecting.
Connecting
The REST API, realtime stream, and the/_/ dashboard are all served on the PocketBase workload’s canonical endpoint, which is public by default (publicAccess.enabled: true). Read it from status.canonicalEndpoint:
200 with a small JSON body means PocketBase is up. From your application, point the official SDK at the base URL:
publicAccess.enabled: false, forward the port instead. PocketBase listens on all interfaces inside the container, so the tunnel reaches it with the firewall fully closed:
http://localhost:8090/_/. Browser traffic through a port-forward is a convenience for setup, not a substitute for the real endpoint.
First Run
There is no setup wizard: the superuser account already exists when PocketBase first starts.Sign in to the dashboard
https://CANONICAL_ENDPOINT/_/ and sign in with the email and password from your credentials secret.Set the Application URL
https://CANONICAL_ENDPOINT. Verification and password-reset emails build their links from this value, so until you set it those links point at the wrong host. It is a database setting, so the template cannot write it for you.Configure SMTP and OAuth2 providers
encryptionKey.Create your collections and API rules
Operations
Backing Up
Two layers protect/pb_data, and they are configured in different places.
Volume set snapshots (configured by the template). On the cron schedule in backup.schedule (default daily at 03:00 UTC), the platform takes a crash-consistent snapshot of RELEASE_NAME-pocketbase-data; SQLite recovers cleanly from one through its write-ahead log. Snapshots are pruned after backup.retention (default 7 days), and a final snapshot is always taken when the release is uninstalled. A snapshot covers everything on the volume: the SQLite database, uploaded files, and any backup archives PocketBase itself wrote locally.
pb_data on demand or on its own schedule. Because the chart runs the server with --dir=/pb_data, local archives land under /pb_data/backups — on the same volume as the database, and therefore inside every volume snapshot. Pointing the backups at an S3 bucket in the same screen is the way to get an off-platform copy; the S3 credentials are stored in the database and encrypted with your encryptionKey. This template deliberately does not configure any of this — it is a database setting with no Helm knob.
Keep a copy of the credentials secret too, especially encryptionKey: a restored database only yields usable SMTP, OAuth2, and S3 settings if PocketBase runs with the same key they were encrypted under.
Restoring a Backup
Two restore paths follow from the two backup layers. Neither has been exercised against a live install of this template — rehearse on a throwaway release before you depend on either. From a volume set snapshot. The platform provisions a fresh volume from the chosen snapshot and swaps it in; the single-replica workload restarts to remount it, and everything written after the snapshot is lost. List the snapshots withcpln volumeset snapshot get RELEASE_NAME-pocketbase-data --gvc GVC_NAME, then restore with cpln volumeset snapshot restore — check cpln volumeset snapshot restore --help for the flags that select the snapshot, location, and volume index. See the volume set reference.
From a PocketBase backup archive. Under Settings → Backups in the dashboard, PocketBase can restore one of its own ZIP archives in place and restart itself. A restore brings back the data as it was when the archive was taken, including the collections, records, uploaded files, and settings. Because the template re-applies the superuser from your secret on every start, the login after a restore is whatever your secret holds, not what the archive held — and the restored settings decrypt only if encryptionKey is unchanged.
Rotating the Superuser Password
The superuser password is re-applied from the credentials secret on every start, so it is rotated by changing the secret and restarting the workload — not from inside the dashboard. Apply the whole secret with the new password, keepingemail and encryptionKey exactly as they are, then force a redeployment (a changed secret is picked up only when the replica restarts):
Scaling and Availability
PocketBase runs as exactly one replica, and there is deliberately noreplicas knob. The database is embedded SQLite with no clustering, so PocketBase scales vertically only — raise resources.maxCpu and resources.maxMemory (keeping maxCpu within 4:1 of minCpu) rather than adding instances. On this platform each stateful replica would also get its own volume, so a second replica would serve a different, empty database behind the same endpoint.
Any restart — a helm upgrade that changes the container, a forced redeployment, or a replica being rescheduled — takes the service offline for a short time while the new replica starts and the volume reattaches. Data is not at risk: the same volume reattaches, and encrypted settings still decrypt. The difference between this single instance and a highly available service is minutes of downtime, not data loss.
Troubleshooting
Deployment never becomes ready and the logs are empty
Deployment never becomes ready and the logs are empty
cpln helm install reported success, cpln logs returns nothing, and cpln workload get-deployments RELEASE_NAME-pocketbase --gvc GVC_NAME -o yaml shows The secret SECRET_NAME no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed. under status.versions[].message.Cause: The dictionary secret named by credentials.secretName does not exist.Fix: Create it (see Prerequisites). The deployment recovers on its own once the secret exists; cpln workload force-redeployment RELEASE_NAME-pocketbase --gvc GVC_NAME skips the wait.Container exits with password must be at least 8 characters
Container exits with password must be at least 8 characters
password: Must be at least 8 character(s).Cause: The password entry in your credentials secret is shorter than PocketBase’s minimum. The chart runs the superuser command with set -e, so a rejected credential is a visible crash rather than a silent skip.Fix: Update the secret with a password of at least 8 characters and force a redeployment (see Rotating the Superuser Password).Container exits with crypto/aes invalid key size
Container exits with crypto/aes invalid key size
crypto/aes: invalid key size 31 (or another number) and the container never serves.Cause: encryptionKey is not a valid AES key length. PocketBase requires exactly 32 characters.Fix: On a fresh install that has never started, recreate the secret with encryptionKey="$(openssl rand -hex 16)" and force a redeployment. On an install that already ran with a valid key, do not change it — restore the original key instead, or every encrypted setting is lost.Render fails saying resources.cpu is not a knob in this chart
Render fails saying resources.cpu is not a knob in this chart
pocketbase: resources.cpu is not a knob in this chart — a block exposing both a reservation and a limit names the limit resources.maxCpu. (or the same for resources.memory).Cause: Your values use the bare cpu / memory names.Fix: Rename them to resources.maxCpu and resources.maxMemory.Password changed in the dashboard is back to the old one after a restart
Password changed in the dashboard is back to the old one after a restart
pocketbase superuser upsert from the credentials secret on every start, so the secret is authoritative.Fix: Change the password in the secret and force a redeployment — see Rotating the Superuser Password.Realtime subscriptions disconnect every ten minutes
Realtime subscriptions disconnect every ten minutes
GET /api/realtime stream ends cleanly after ten minutes even while events are flowing; a hand-rolled client stops receiving updates.Cause: Realtime is Server-Sent Events — one long HTTP response — and the workload’s request timeout (timeoutSeconds, set to 600, the platform maximum) closes it. PocketBase also closes a stream that receives no events for five minutes, by its own design. Nothing is lost while the stream is open, and the cut is a normal end-of-stream.Fix: The official PocketBase SDKs reconnect and resubscribe automatically. A custom EventSource or curl consumer must reconnect and resubscribe when the stream ends.PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD have no effect
PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD have no effect
entrypoint.sh, which this chart replaces with its own command. PocketBase itself reads no environment variables for configuration.Fix: The superuser is defined by the email and password keys of your credentials secret; nothing else is consulted.Browser requests to the API are blocked by CORS
Browser requests to the API are blocked by CORS
access-control-allow-origin header, while the same request from curl returns 200.Cause: cors.allowedOrigins does not include your app’s origin.Fix: Add the origin (scheme and host, e.g. https://app.example.com) to cors.allowedOrigins and upgrade the release; the change applies once the new replica is serving.Verification and password-reset emails link to the wrong host
Verification and password-reset emails link to the wrong host
localhost or a hostname that is not your endpoint.Cause: Settings → Application → Application URL has not been set. It is a database setting the chart cannot write.Fix: Set it to https://CANONICAL_ENDPOINT in the dashboard (see First Run).Important Notes
- Create the credentials secret before installing. Without it the deployment wedges silently:
cpln logsreturns nothing and the only diagnostic isstatus.versions[].messagefromcpln workload get-deployments. - Never change
encryptionKeyafter install. It encrypts the SMTP password, OAuth2 client secrets, and S3 backup credentials in the database; a changed key orphans all of them. Keep a copy outside Control Plane. - The secret is the superuser login at every restart. A password changed in the dashboard is reverted; change it in the secret and force a redeployment. See Rotating the Superuser Password.
- Rotating the secret needs a forced redeployment. The workload does not pick up a changed secret on its own, and nothing warns you — the old password keeps working until the replica restarts.
- Single instance, no HA, and that is upstream’s design. There is no
replicasknob; every restart is a brief outage, and data is not at risk because the same volume reattaches. See Scaling and Availability. - Realtime connections end after ten minutes at most. The official SDKs reconnect automatically; a hand-rolled client must handle it.
- Set the Application URL at first login. Emails link to the wrong host until Settings → Application → Application URL is set.
- Uploads and local backup archives share the volume with the database. A file-heavy app needs more than the 10 GiB default; set
volumeset.capacityat install time. - Snapshots are not an off-platform copy. For one, configure PocketBase’s own S3 backups under Settings → Backups.
- Restore paths are unverified against this template. Rehearse a snapshot or archive restore on a throwaway release before relying on it.
- This is a community image with its entrypoint replaced.
PB_ADMIN_EMAILandPB_ADMIN_PASSWORDdo nothing here; animageoverride must run as root withpocketbaseonPATH. - Data survives restarts and upgrades; uninstalling deletes the volume set after taking a final snapshot. Your credentials secret is yours and survives an uninstall.