Skip to main content

PocketBase Common — Shared Application Configuration

PocketBase_Common is the shared application layer for PocketBase. It is not deployed on its own; instead it supplies the PocketBase-specific configuration that both PocketBase_GKE and PocketBase_CloudRun build on, so the two platform variants behave identically where it matters. End users never configure this layer directly — it has no deployment UI inputs of its own — but understanding what it provides explains the defaults you see in the platform docs.

For the infrastructure that actually provisions and runs PocketBase, see the platform guides (PocketBase_GKE, PocketBase_CloudRun) and the foundation guides (App_GKE, App_CloudRun, App_Common).


1. What this layer provides

AreaProvided by PocketBase_CommonWhere it surfaces
Container imageWraps the prebuilt ghcr.io/muchobien/pocketbase image via a thin Dockerfile so the foundation can build/mirror it into Artifact Registrycontainer_image output of the platform deployment
Image versionPins POCKETBASE_VERSION to 0.22.21 when application_version = "latest", so a non-existent pocketbase:latest-derived tag is never requestedcontainer_build_config.build_args
Database engineFixes database_type = "NONE" — PocketBase ships an embedded SQLite database; no Cloud SQL instance is created§Database behaviour in the platform guides
Database bootstrapNone — PocketBase self-creates and migrates its own SQLite schema on first boot, so no db-init job is injectedApplication behaviour in the platform guides
Persistent storageDeclares a single Cloud Storage data bucket (suffix storage) and mounts it at /pb_data on Cloud Run via GCS FUSE; on GKE a block PVC is mounted at the same path insteadstorage_buckets output
SecretsNone — PocketBase issues and stores all auth in its own SQLite DB; secret_ids / secret_values are intentionally empty§Secrets below
Cache / queueNone — PocketBase is a single self-contained backend and does not use RedisBoth variants set enable_redis = false
Core settingsContainer port 8090, admin created interactively at /_/, no env required for first bootApplication behaviour in the platform guides
Health checksSupplies the default startup/liveness probe targeting /api/health§Observability in the platform guides

2. Secrets in Secret Manager

PocketBase requires no injected secret. Unlike most database-backed applications, PocketBase has no env-supplied credential:

  • The superuser (admin) account is created interactively on first access at /_/.
  • All API authentication (admin tokens, user records, auth collections) is issued and stored by PocketBase itself inside its embedded SQLite database under /pb_data.

Because of this, PocketBase_Common deliberately exports empty secret_ids and secret_values maps. The CloudRun and GKE variants still reference these outputs (wiring them into module_secret_env_vars / explicit_secret_values) so the module contract is uniform with every other application module — but no Secret Manager secret is created for PocketBase's own auth.

If you add your own secrets (for example, an SMTP password or an S3 access key for external backups), inject them through the platform's secret_environment_variables input on the variant module and confirm them with:

gcloud secrets list --project "$PROJECT" --filter="name~pocketbase"
gcloud secrets versions access latest --secret=<secret-name> --project "$PROJECT"

The durable secret to protect is not in Secret Manager at all — it is the SQLite database in the data bucket / PVC, which holds every record, admin, and token.


3. Container image

The image is a thin wrapper built from the prebuilt upstream image:

ARG POCKETBASE_VERSION=0.22.21
FROM ghcr.io/muchobien/pocketbase:${POCKETBASE_VERSION}
  • Base image: ghcr.io/muchobien/pocketbase — a maintained container distribution of the single-binary PocketBase server.
  • Build: the foundation builds this Dockerfile with Cloud Build (Kaniko) and pushes it into the deployment's Artifact Registry repository; enable_image_mirroring = true by default.
  • App-specific version ARG. The Dockerfile reads POCKETBASE_VERSION, not the generic APP_VERSION the foundation injects (and would otherwise force to latest). PocketBase_Common sets POCKETBASE_VERSION = "0.22.21" whenever application_version = "latest", so the build always resolves to a real, existing tag.
  • No custom entrypoint. The upstream image already runs serve --http=0.0.0.0:8090 with its data directory at /pb_data, matching the container port and the storage mount — so no wrapper entrypoint is needed for first boot.

4. Database initialization

There is no database initialization job. PocketBase is a single self-contained Go binary with an embedded SQLite database. On first start it creates its own database files, tables, and system collections under /pb_data, and it applies any pending schema migrations automatically on every subsequent start.

Consequently PocketBase_Common:

  • sets database_type = "NONE" (no Cloud SQL instance, user, or database is provisioned),
  • injects no default initialization_jobs (custom jobs are still accepted via the initialization_jobs input for bespoke data-loading tasks), and
  • performs no pgvector/extension setup and requires no enable_cloudsql_volume.

The only thing that must persist across restarts is the /pb_data directory — see the next section.


5. Persistent storage

PocketBase keeps its entire state — the SQLite database, uploaded files, and settings — under a single directory, /pb_data. PocketBase_Common declares one Cloud Storage data bucket for this and mounts it differently per platform:

PlatformPersistence at /pb_dataHow it is wired
Cloud RunGCS FUSE volume backed by the storage bucketenable_gcs_storage_volume = true injects the bucket as a FUSE mount at /pb_data
GKEBlock PVC (ReadWriteOnce) via a StatefulSetstateful_pvc_enabled = true mounts a block PVC at /pb_data; the Common layer sets enable_gcs_storage_volume = false in this case to avoid a double-mount at the same path

The bucket is declared with:

  • name_suffix = "storage", resolved by the foundation to gcs-<service_name>-storage,
  • location = "" so the foundation places it in the auto-discovered deployment region (a hard-coded location would pin it and could force-replace the immutable-location bucket on re-apply in another region),
  • storage_class = "STANDARD", force_destroy = true, versioning_enabled = false,
  • public_access_prevention = "enforced".

List the bucket after deployment:

gcloud storage buckets list --project "$PROJECT" --filter="name~storage"
gcloud storage ls gs://<data-bucket>/ # bucket name is in the platform Outputs

SQLite locking note. SQLite relies on filesystem locks. A block PVC (GKE default) provides reliable POSIX locking; GCS FUSE (Cloud Run) is the pragmatic single-instance option. Either way, PocketBase must run as one instance (max_instance_count = 1) — concurrent writers against one SQLite file corrupt data.


6. Health probe behaviour

Both variants default their startup and liveness probes to /api/health — PocketBase's public, unauthenticated health endpoint, which returns HTTP 200 once the server is ready. Because there is no external database to wait on, first boot is fast; the default startup probe uses a 15-second initial delay with a 10-retry window, which is comfortable for SQLite initialization.

Verify it directly once the service is up:

curl -s "$SERVICE_URL/api/health"      # {"code":200,"message":"API is healthy.", ...}

For the PocketBase-specific, user-facing configuration (variables by group, outputs, and how to explore each service from the Console and CLI), see the platform guides: PocketBase_GKE and PocketBase_CloudRun.