Skip to main content

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.
This template does not create a GVC. It deploys into an existing GVC that you already have.

What Gets Created

The credentials secret is not created by the template; you create it before installing (see Prerequisites). PocketBase has no external database or cache — it talks to nothing but its own volume.

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.
1

Create the credentials secret

The secret must have exactly these three keys:
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.
2

Keep a copy of the encryption key

Store encryptionKey somewhere safe outside Control Plane. It can never be changed after install without orphaning everything it protects. Read it back any time with:
The secret is the login, at every restart. The container runs pocketbase superuser upsert with the email and password from this secret before the server binds its port, on every start. Changing the password in the dashboard is reverted at the next restart — change it in the secret instead, then force a redeployment (see Rotating the Superuser Password).
A missing prerequisite secret wedges the deployment silently. cpln helm install still succeeds, all four resources are created, and the workload never becomes ready. cpln logs returns nothing at all, because the container never ran. The only place the reason appears is status.versions[].message, which names the missing secret:
Note this is get-deployments — plain cpln workload get has no versions key. Create the missing secret and the deployment recovers on its own, or force a redeployment to skip the wait:
Nothing else is required. Backups are scheduled volume set snapshots managed by the platform and need no bucket or cloud account — see Backing Up.

Installation

Once the credentials secret exists, install from the marketplace registry, naming the secret:
Or follow the instructions for your preferred method:

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Configuration

PocketBase Instance

The 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.
The PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD environment variables described for this image do nothing here. They belong to the image’s own entrypoint.sh, which this chart does not run. PocketBase itself reads no environment variables for configuration — everything is either a CLI flag the chart sets or a dashboard setting. If you override image, it must run as root with pocketbase on PATH.

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

Backups are scheduled, crash-consistent snapshots of the data volume, managed by the platform — no cloud account or bucket is required. 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

Public access is safe to leave on: the superuser is created from your secret before the server starts listening, so no unclaimed admin account is ever exposed, and new collections are superuser-only until you write an API rule that opens them. With publicAccess.enabled: false, external requests are refused and you reach the dashboard through a port-forward — see Connecting. Access changes are not instantaneous; re-test after a pause rather than concluding a knob did not work.

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:
Verify the instance is serving before you sign in:
A 200 with a small JSON body means PocketBase is up. From your application, point the official SDK at the base URL:
With 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:
Then open 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.
1

Sign in to the dashboard

Open https://CANONICAL_ENDPOINT/_/ and sign in with the email and password from your credentials secret.
2

Set the Application URL

Go to Settings → Application → Application URL and set it to 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.
3

Configure SMTP and OAuth2 providers

Both live under Settings, in the database rather than in Helm values, and are encrypted at rest with your encryptionKey.
4

Create your collections and API rules

New collections are superuser-only until you write an API rule that opens them.

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.
Snapshots live in the platform storage layer alongside the volume, not off-site — they protect against data corruption and accidental changes, but they are not an off-platform copy. PocketBase’s own backups (configured in the dashboard). Under Settings → Backups, PocketBase can create ZIP archives of 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 with cpln 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.
Both paths restart the only replica, so PocketBase is unavailable while the restore completes, and both revert everything written after the backup was taken.

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, keeping email and encryptionKey exactly as they are, then force a redeployment (a changed secret is picked up only when the replica restarts):
Until the new replica is serving, the old password continues to work and the workload reports ready against the outgoing replica. There is no error and no warning if you skip the redeployment — the old credential simply stays valid.
Never change encryptionKey in this manifest. It encrypts the SMTP password, OAuth2 client secrets, and S3 backup credentials stored inside the database; a different key orphans all of them with no way back.

Scaling and Availability

PocketBase runs as exactly one replica, and there is deliberately no replicas 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

Symptom: 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.
Symptom: The workload restarts repeatedly and the logs show 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).
Symptom: The logs show 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.
Symptom: 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.
Symptom: You changed the superuser password under the dashboard’s settings; after an upgrade or redeployment the old password works again and the new one is rejected.Cause: The chart runs 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.
Symptom: A long-lived 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.
Symptom: You set the environment variables documented for the community image and the superuser login did not change.Cause: Those variables are read by the image’s own 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.
Symptom: The browser console shows a CORS error and the response has no 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.

Important Notes

  • Create the credentials secret before installing. Without it the deployment wedges silently: cpln logs returns nothing and the only diagnostic is status.versions[].message from cpln workload get-deployments.
  • Never change encryptionKey after 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 replicas knob; 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.capacity at 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_EMAIL and PB_ADMIN_PASSWORD do nothing here; an image override must run as root with pocketbase on PATH.
  • Data survives restarts and upgrades; uninstalling deletes the volume set after taking a final snapshot. Your credentials secret is yours and survives an uninstall.

External References

PocketBase Documentation

Official documentation for collections, API rules, and the dashboard

REST API Reference

Reading and writing records over the auto-generated API

Realtime API

Server-Sent Events subscriptions and the reconnect model

Going to Production

Upstream guidance, including settings encryption and backups

PocketBase Template

View the source files, default values, and chart definition