Skip to main content

ClassicPress on GKE Autopilot

ClassicPress on GKE Autopilot

ClassicPress is a free, open-source, business-focused CMS — a lightweight fork of WordPress 4.9.x that preserves the classic (pre-Gutenberg) editing experience, with plugins, themes, a media library, and a REST API. This module deploys ClassicPress on GKE Autopilot on top of the App_GKE foundation, which provisions and manages the shared Google Cloud and Kubernetes infrastructure.

This guide focuses on the cloud services ClassicPress uses and how to explore and operate them from the Google Cloud Console and the command line. For the mechanics that are common to every GKE application — Workload Identity, ingress, autoscaling, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC Service Controls, backups, and the deployment lifecycle — refer to the App_GKE foundation guide rather than repeating them here.


What ClassicPress costs on RAD, and how that compares​

ClassicPress on RAD's GKE Autopilot module costs about US$110.13 a month in a Google Cloud project you own, plus a one-time 175-credit module fee (US$17.50). ClassicPress is a lightweight, pre-Gutenberg fork of WordPress for business sites. For the lowest cost, the Cloud Run guide runs the same ClassicPress for about US$83.61 a month; pick GKE here only if ClassicPress must stay up continuously, scale across pods, or run beside other Kubernetes workloads.

If ClassicPress is only needed occasionally — a demo, a trial, a seasonal or study workload — a RAD-managed project can be deleted and restored within 30 days for a handful of credits, so that US$110.13 becomes a few dollars a month instead. See Pause it for free, below.

What you pay on RAD​

In a Google Cloud project you ownIn a project RAD manages for you
Module fee, once per deployment175 credits (US$17.50 at the top-up price)157.5 credits (10% lower)
Build timeA few credits per build (roughly 3–6)The same
Google Cloud running costBilled by Google to your own billing account, about US$110.13 a month for the default configuration (table below)Metered hourly in credits; RAD publishes 99 credits a day, about 2970 a month (about US$297 at the top-up price)
Who owns whatYou own the project and its billing; RAD deploys and updates itRAD owns the project, with guardrails, quotas and budget alerts; you get console access, and a minimum purchased balance is held in reserve

10 credits cost US$1 on a one-off top-up, less on a plan. In a project RAD manages, the database, file server and network are shared by every application in the project, so a second application does not add a second database.

Default running cost in your own project (us-central1, Google list prices):

Resource (module default)Per month
GKE Autopilot pod, 1x vCPU / 2 GiBUS$39.68
Cloud SQL for MySQL, 1 vCPU / 3.75 GB, zonal, 10 GB SSDUS$51
NFS/cache file server (small VM)US$13.43
Cloud NAT and networkingUS$5
Cloud Storage (add-ons, backups)US$1
GKE cluster management feeshared across every GKE app in the project; $0 if this is your only cluster, else ~73
Totalabout US$110.13

How it compares​

  • Run it yourself and a VPS running PHP, MySQL and ClassicPress yourself costs less in cash: a Hetzner CPX22 or DigitalOcean 2 vCPU/4 GB box is about $24 a month, or a GCP e2-standard-2 about $49 a month — plus your own time for backups, security patches and upgrades, which RAD's managed Cloud SQL, Secret Manager and monitoring cover for you.
  • RAD never claims to be cheaper than bare infrastructure in cash terms — it usually is not. The difference is what RAD manages for you: patching, backups, secrets and monitoring, plus the ability to pause ClassicPress for free rather than paying for idle capacity (see below).
  • Most of the running cost above is the managed MySQL database (and, where used, the shared file server) — the part a bare VPS comparison has to run and back up by hand.

Pause it for free: delete a RAD-managed project, restore it when you need it​

If ClassicPress runs in a project RAD manages for you, you have a second option that goes well beyond scaling to zero: delete the whole project, and restore it within 30 days for close to nothing. This suits ClassicPress that you only need occasionally far better than running it continuously.

  • How it works. Deleting a RAD-managed project unlinks its billing first, then asks Google to delete the project. Google does not remove the project immediately: it keeps it, recoverable, for 30 days. Because billing is already unlinked, nothing is charged while it waits. Unlike deleting one module, this does not tear down Cloud SQL, the VM or GKE Autopilot resources one by one — the whole project, and everything in it, simply stops.
  • Restoring costs a handful of credits, not a rebuild. Within 30 days, the project's owner can restore it. RAD asks Google to undelete the project and reattaches its billing account, then asks you to run Update on each deployment to confirm everything came back. Because nothing was individually destroyed, that Update finds the same resources already there — it is a check, not a rebuild, and an Update never charges the module fee again. That is a handful of credits (under US$1) in total for a typical ClassicPress chain, against the 180 credits a full redeploy costs.
  • So a month of occasional use can cost a few dollars, not US$110.13. Deploy ClassicPress, use it, delete the project. Restore it next time you want it, confirm with Update, and delete it again when you're done. You pay only for the module fee once, the builds, and whatever hours it was actually live.
  • What this needs. You must own the project (not a bring-your-own one RAD only manages billing for), and you restore it yourself within the 30 days — after that, Google deletes it for good. Restoring is admitted like creating a new project: your purchased credit balance must still clear the tier's floor (100 credits for the sandbox tier most study and demo use fits). Google says most services are fully working again within 36 hours of a restore.
  • One real gap: the backup bucket does not survive. Nightly backups are written to a bucket inside the project, and that bucket is not protected by Cloud Storage's soft-delete, so it is very likely gone as soon as you delete the project — even though the project itself is recoverable for 30 days. If you have customised ClassicPress and want to keep that work, copy a backup out (to Google Drive, or a bucket outside the project) before you delete. For a default installation with nothing irreplaceable in it, this does not matter.

Pay only while you use it, the other way: delete and redeploy​

GKE Autopilot keeps at least one pod running, so it never scales to zero on its own. The option above only applies to a RAD-managed project; in your own project, or once the 30-day window has passed, the way to stop paying is to delete the deployment and deploy it again when you need it.

  • What a redeploy costs. The module fee again plus the builds: about 180 credits (US$18) in your own project. Deleting saves money only once ClassicPress would otherwise sit unused for about 5 days or more in your own project (US$3.67 a day), or about 2 days or more in a RAD-managed one (99 credits a day).
  • Most of the running cost is usually the database and the shared file or cache server. They stop only when nothing else in the project uses them, so deleting ClassicPress while something else shares the project saves only this app's own compute part.
  • Keep your data first. Nightly backups are written to a bucket inside the deployment and are deleted with it, so copy the latest backup out before deleting if you want to keep it.
  • Note your settings. RAD does not recreate a deleted deployment for you; you enter the settings again when you deploy.

Lab sessions and Managed Environments​

  • Lab sessions, for training. A trainer runs a session for a class. Each participant gets the app in their own Google Cloud project for 15 minutes to 24 hours, within an allowance the trainer sets. Either the trainer funds every place, or each participant pays for their own. Everything is deleted when the session ends and unused credits go back to the trainer.
  • Managed Environments, for consultancies. A partner runs the app for a client from a ring-fenced wallet it funds, and settles with the client directly. If the wallet runs low, billing pauses and the data is kept, so nobody receives an unexpected charge. At the end the partner hands the project over and the deployments become the client's own.

Credits can be bought in more than 20 currencies, including XAF, XOF, NGN, GHS, KES and ZAR, by card, bank transfer or mobile money.

Sources (8 October 2026): Google Cloud list prices from the Cloud Billing Catalog API; RAD's own fees and daily-credit estimates from radmodules.dev/pricing; Delete and restore projects for the 30-day recovery window and what it says about Cloud Storage objects without soft delete. Prices change; check each source before relying on a figure.

1. Overview​

ClassicPress runs as a single PHP/Apache web workload built from a thin custom image FROM classicpress/classicpress. The deployment wires together a focused set of Google Cloud services:

CapabilityGoogle Cloud serviceNotes
ComputeGKE AutopilotPHP/Apache pod on port 80, 1 vCPU / 2 GiB by default
Workload shapeKubernetes StatefulSet + block PVCstateful_pvc_enabled = true auto-resolves workload_type to StatefulSet; a 10Gi standard-rwo (SSD) PVC is mounted at /var/www/html — the whole ClassicPress install (code, plugins, themes, wp-content/uploads) lives on this per-pod volume
DatabaseCloud SQL for MySQL 8.0Fixed — ClassicPress_Common hardcodes database_type = "MYSQL_8_0"
File persistence (secondary)Cloud Filestore (NFS)Mounted at /var/www/html/wp-content by default (enable_nfs = true) — a subpath of the StatefulSet PVC below; this is the confirmed mechanism for upload/plugin/theme persistence (see Section 3)
Object storageCloud StorageA classicpress-uploads bucket is provisioned automatically but is not mounted into the pod by default
SecretsSecret ManagerAuto-generated CLASSICPRESS_SALT_SEED (derives the 8 WordPress-style auth keys/salts); database password
IngressCloud Load BalancingExternal LoadBalancer with a reserved static IP; custom domain + managed certificate enabled by default

Sensible defaults worth knowing up front:

  • MySQL 8.0 is mandatory and hardcoded. ClassicPress_Common's config sets database_type = "MYSQL_8_0" directly; the variant's database_type variable (default null) only takes effect if explicitly overridden, and doing so breaks the MySQL-specific db-init job and entrypoint. Leave it null.
  • Custom build, not prebuilt. container_image_source defaults to "custom" — Cloud Build produces a thin image FROM classicpress/classicpress that grafts an entrypoint shim aliasing the Foundation's injected DB_* vars onto ClassicPress's CLASSICPRESS_DB_* and deriving stable auth salts. The stock upstream image is never deployed directly.
  • Cloud SQL is reached via the Auth Proxy sidecar on loopback. The variant sets DB_HOST = 127.0.0.1; a cloud-sql-proxy sidecar (enable_cloudsql_volume = true) listens on 127.0.0.1:3306, and the entrypoint aliases the injected DB_* values onto CLASSICPRESS_DB_* (TCP, no SSL needed for MySQL).
  • Single replica, StatefulSet by default. min_instance_count = 1, max_instance_count = 1. Each pod gets its own PVC via stateful_pvc_enabled = true (default), so scaling beyond 1 replica would give each pod a separate, unsynced copy of the install rather than a shared one.
  • NFS is also enabled by default (enable_nfs = true, mounted at /var/www/html/wp-content — a subdirectory of the StatefulSet PVC mount below). ClassicPress reads/writes uploaded media, plugins, and themes under wp-content, and the upstream entrypoint's first-boot copy logic explicitly skips an existing wp-content directory, so this mount is a genuine, confirmed persistence path for that data — not spare/unused storage. See the pitfalls table.
  • No auto-install — first login is manual. ClassicPress_Common generates no admin-password secret and sets no auto-install flag. ClassicPress creates its schema and admin account through its own first-run web installer once db-init has provisioned the empty database.
  • CLASSICPRESS_SALT_SEED is generated automatically and stored in Secret Manager; the entrypoint derives all 8 WordPress-style AUTH_KEY/SALT values from it deterministically, so cookies and sessions survive pod restarts.
  • Startup probe is generous (TCP, 20 retries) to allow time for the upstream image's own entrypoint to populate the empty /var/www/html PVC on first boot.

2. Google Cloud Services & How to Explore Them​

All commands assume you have run gcloud container clusters get-credentials <cluster> --region "$REGION" --project "$PROJECT" and that PROJECT, REGION, and NAMESPACE are set. The namespace and other identifiers are reported in the deployment Outputs.

A. GKE Autopilot — the ClassicPress workload​

ClassicPress runs as a StatefulSet (auto-selected because stateful_pvc_enabled defaults to true), scheduled on Autopilot, which bills for the CPU/memory the pod actually requests. The single replica owns a dedicated standard-rwo (SSD) PVC.

  • Console: Kubernetes Engine → Workloads → select the ClassicPress workload for pods, revisions, and events. Kubernetes Engine → Services & Ingress shows the external IP.
  • CLI:
    kubectl get statefulset,pods,svc -n "$NAMESPACE" --selector 'app~classicpress' 2>/dev/null || \
    kubectl get statefulset,pods,svc -n "$NAMESPACE"
    kubectl logs -n "$NAMESPACE" statefulset/<service-name> --tail=100
    kubectl describe pod -n "$NAMESPACE" -l app=<service-name>

See App_GKE for how Autopilot, scaling, and the workload type (Deployment vs StatefulSet) are managed, and Group 7 for StatefulSet/PVC mechanics.

B. Cloud SQL for MySQL 8.0​

ClassicPress stores all application data (posts, pages, users, options, plugin/theme settings) in a managed Cloud SQL for MySQL 8.0 instance. Pods reach it through the Cloud SQL Auth Proxy sidecar on 127.0.0.1:3306; no public IP is exposed. On first deploy the db-init job creates the application database, user, and grants, verifies the app user can connect, then shuts the sidecar down.

  • Console: SQL → select the instance for connections, backups, flags, metrics.
  • CLI:
    gcloud sql instances list --project "$PROJECT"
    gcloud sql instances describe <instance-name> --project "$PROJECT"
    gcloud sql connect <instance-name> --user=<db-user> --database=<db-name> --project "$PROJECT"

The instance name, database, user, and the Secret Manager secret holding the password are all in the Outputs. See App_GKE for the connection model, automated backups, and password rotation.

C. Storage — StatefulSet PVC, NFS, and Cloud Storage​

Three distinct storage mechanisms are present. The StatefulSet PVC (10Gi, standard-rwo, mounted at /var/www/html) holds the entire ClassicPress install, including uploaded media — persistence for the whole webroot as long as the pod keeps its PVC. NFS (Cloud Filestore) is separately mounted at /var/www/html/wp-content (enable_nfs = true), a subdirectory of the PVC mount above; the upstream entrypoint's copy logic explicitly skips an existing wp-content directory, so this is a genuine, confirmed persistence path for uploads/plugins/themes specifically — not an unused mount (see the pitfalls table). A Cloud Storage bucket (suffix classicpress-uploads) is also provisioned but not wired into the pod as a gcs_volumes mount by default; add an entry to gcs_volumes to use it.

  • Console: Kubernetes Engine → Storage → PersistentVolumeClaims; Filestore → Instances; Cloud Storage → Buckets.
  • CLI:
    kubectl get pvc -n "$NAMESPACE"
    gcloud filestore instances list --project "$PROJECT"
    gcloud storage buckets list --project "$PROJECT" --filter="name~classicpress-uploads"

See App_GKE Groups 7, 13, and 14 for PVC lifecycle, NFS discovery, and GCS Fuse mount mechanics.

D. Secret Manager​

One ClassicPress-specific secret is generated automatically and stored in Secret Manager: CLASSICPRESS_SALT_SEED, a 64-character random seed from which the entrypoint derives all 8 WordPress-style AUTH_KEY/SECURE_AUTH_KEY/ LOGGED_IN_KEY/NONCE_KEY and their matching SALT values (SHA-256 of the seed plus a fixed per-key suffix). The database password is managed separately by the foundation. On GKE, secrets are projected into pods via the Secret Store CSI driver.

  • Console: Security → Secret Manager.
  • CLI:
    gcloud secrets list --project "$PROJECT" --filter="name~classicpress"
    gcloud secrets versions access latest --secret=<db-password-secret-name> --project "$PROJECT"

See App_GKE for the Secret Store CSI integration and rotation.

E. Networking & ingress​

By default the workload is exposed through an external Cloud Load Balancing IP (service_type = LoadBalancer, reserve_static_ip = true so the address survives redeploys), and enable_custom_domain = true provisions an Ingress resource ready for a Google-managed certificate once application_domains is populated.

  • Console: Network services → Load balancing; VPC network → IP addresses.
  • CLI:
    kubectl get svc,ingress -n "$NAMESPACE"
    gcloud compute addresses list --project "$PROJECT"

See App_GKE for custom domains, Cloud CDN, and static IP details.

F. Cloud Logging & Monitoring​

Pod stdout/stderr flow to Cloud Logging; GKE and Cloud SQL metrics flow to Cloud Monitoring. Optional uptime checks and alert policies are available.

  • Console: Logging → Logs Explorer; Monitoring → Dashboards / Alerting.
  • CLI:
    gcloud logging read 'resource.type="k8s_container" AND resource.labels.namespace_name="'"$NAMESPACE"'"' \
    --project "$PROJECT" --limit 50

3. ClassicPress Application Behaviour​

  • First-deploy database setup. The db-init job runs db-init.sh using mysql:8.0-debian. It waits for TCP connectivity (or a Cloud SQL socket), idempotently creates the application database, user, and grants, verifies the app user can connect, then gracefully shuts down the Cloud SQL Auth Proxy sidecar (POST /quitquitquit, falling back to SIGKILL). The job is safe to re-run (execute_on_apply = true, max_retries = 3).
  • No separate migration job — manual first-run install. There is no auto-install flag for ClassicPress. Once db-init has provisioned the empty database, ClassicPress creates its own schema and admin account through the first-run web installer (/wp-admin/install.php in the upstream image). Visit the service URL after first deploy and complete the installer to set the admin username, password, and email — there is no generated admin-password secret.
  • DB env-var aliasing on loopback. The Foundation injects DB_HOST = 127.0.0.1 (the proxy sidecar), DB_PORT, DB_NAME, DB_USER, DB_PASSWORD; ClassicPress reads CLASSICPRESS_DB_*. The grafted entrypoint.sh builds CLASSICPRESS_DB_HOST as host:port (or a localhost:<socket> form if a Cloud SQL socket directory is found) and aliases the rest, before handing off to the upstream docker-entrypoint.sh.
  • Auth keys/salts are derived, not stored individually. CLASSICPRESS_SALT_SEED is the only generated secret; the entrypoint computes all 8 CLASSICPRESS_AUTH_KEY / ..._SALT values as sha256(seed-<key-name>), so every restart and every pod (if you ever scale out) agrees on the same values without persisting wp-config.php state.
  • The install itself lives on the StatefulSet PVC. The upstream docker-entrypoint.sh writes wp-config.php and copies the ClassicPress application into /var/www/html on first boot — which on this module is a 10Gi standard-rwo block PVC, not ephemeral container storage, so the install (plugins, themes, and wp-content/uploads) survives pod restarts and rescheduling.
  • NFS mount path is the confirmed persistence mechanism for wp-content. enable_nfs = true mounts Filestore at /var/www/html/wp-content by default — a subdirectory of the StatefulSet PVC mounted at /var/www/html. ClassicPress (a WordPress fork) reads/writes uploaded media, plugins, and themes under wp-content, and the upstream entrypoint's first-boot copy logic explicitly skips an existing wp-content directory, so mounting NFS there is safe and effective. On this module the PVC already persists the whole webroot per-pod, so the NFS mount is most valuable if stateful_pvc_enabled is ever disabled or a future multi-replica scale-out needs wp-content shared across pods (the PVC is per-pod, NFS is shared).
  • Redis is optional and off by default. When enable_redis = true, leaving redis_host empty lets the Foundation's own REDIS_HOST injection (the shared NFS-VM Redis IP when enable_nfs = true) take effect; setting redis_host explicitly points ClassicPress at an external Redis/Memorystore instance instead.
  • Health paths. Startup probe is TCP on port 80 with a generous failure_threshold = 20 (first boot copies the whole application onto the empty PVC, which can take time); liveness probe is HTTP GET / with a 300-second initial delay — a 200 (installed site) or a 302 redirect to the installer (fresh site) both count as healthy.
  • Inspect the init job and running config:
    kubectl get jobs -n "$NAMESPACE"
    kubectl logs -n "$NAMESPACE" job/<db-init-job-name>
    kubectl exec -n "$NAMESPACE" statefulset/<service-name> -- env | grep CLASSICPRESS_DB

4. Configuration Variables​

Variables are grouped exactly as they appear on the deployment platform (by their {{UIMeta group=N}} tag, not by the .tf file's section comments, which are occasionally out of sync with the tags). Only settings specific to or notable for ClassicPress are listed; every other input is inherited from App_GKE with its standard behaviour and defaults.

Group 3 — Application Identity​

VariableDefaultDescription
application_nameclassicpressBase name for resources. Do not change after first deploy.
application_versionlatestMaps to the classicpress/classicpress image tag. Tags are PHP-qualified (php8.3-apache, php8.4-apache), not version-qualified; latest resolves to a pinned PHP-qualified tag at build time via the app-specific CLASSICPRESS_VERSION build arg (the generic APP_VERSION build arg the Foundation injects would otherwise silently overwrite it with the literal, non-existent tag "latest").

Group 4 — Runtime & Scaling​

VariableDefaultDescription
container_image_sourcecustomBuilds the thin FROM classicpress/classicpress image with the grafted entrypoint shim; required — the stock image cannot alias DB_* on its own.
cpu_limit1000mCPU limit for the ClassicPress container. Increase for high-traffic sites or heavy plugins.
memory_limit2GiMemory limit. WordPress-family apps typically need ≥512Mi; more for large media libraries.
min_instance_count / max_instance_count1 / 1Keep both at 1 — the StatefulSet PVC is per-pod and not shared.
container_port80ClassicPress runs on Apache, port 80.
php_memory_limit512MPHP memory limit; must be ≤ memory_limit.
upload_max_filesize / post_max_size64MMax upload / POST size; keep post_max_size ≥ upload_max_filesize.
enable_cloudsql_volumetrueAuth Proxy sidecar (loopback) — required on GKE.

Group 6 — GKE Backend & Cluster​

VariableDefaultDescription
service_typeLoadBalancerExternal IP for the ClassicPress UI.
workload_typenull → StatefulSetAuto-resolved because stateful_pvc_enabled = true.
session_affinityClientIPSticky routing so a client reaches the same pod.

Group 7 — StatefulSet / PVC​

VariableDefaultDescription
stateful_pvc_enabledtrueClassicPress stores its whole install under /var/www/html; enabling this auto-resolves workload_type to StatefulSet.
stateful_pvc_size10GiPer-pod PVC size. Raise for large media libraries.
stateful_pvc_mount_path/var/www/htmlWhere the ClassicPress install (code + wp-content/uploads) lives.
stateful_pvc_storage_classstandard-rwoSSD-backed Balanced PD; draws the SSD_TOTAL_GB regional quota. Override to standard (HDD) if quota-constrained.

Group 10 — Observability & Health​

VariableDefaultDescription
startup_probe{ type: TCP, path: "/", failure_threshold: 20, period_seconds: 15 }Generous threshold — first boot populates the empty PVC with the full application.
liveness_probe{ type: HTTP, path: "/", initial_delay_seconds: 300 }A 200 or a 302-to-installer both count as healthy.

Group 13 — Filesystem (NFS)​

VariableDefaultDescription
enable_nfstrueProvisions Filestore-backed shared storage mounted at nfs_mount_path — the confirmed persistence mechanism for uploads/plugins/themes; see Section 3.
nfs_mount_path/var/www/html/wp-contentContainer mount path for the NFS share, a subdirectory of the StatefulSet PVC. The upstream entrypoint's copy logic skips an existing wp-content directory, so mounting here is safe.

Group 15 — Redis Cache​

VariableDefaultDescription
enable_redisfalseEnables ClassicPress's WordPress-style object cache backend.
redis_host""Leave empty to fall back to the Foundation's own REDIS_HOST (the NFS-VM Redis IP when enable_nfs = true); set explicitly to use an external Redis/Memorystore instance.

Group 16 — Database Backend​

VariableDefaultDescription
database_typenull → MYSQL_8_0Hardcoded in ClassicPress_Common; leave null. Overriding it breaks the MySQL-specific db-init job and entrypoint.
application_database_nameclassicpressDatabase name. Immutable after first deploy.
application_database_userclassicpressApplication database user; password auto-generated in Secret Manager.

Group 19 — Custom Domain, Static IP & Networking​

VariableDefaultDescription
enable_custom_domaintrueProvisions an Ingress ready for a managed certificate once application_domains is set.
reserve_static_iptrueStable external IP across redeploys.
application_domains[]Custom hostnames — empty by default; add one to activate the managed certificate.

All other inputs follow standard App_GKE behaviour.


5. Outputs​

These values are returned on a successful deployment and are the quickest way to locate and explore the running resources.

OutputDescription
service_nameKubernetes Service name.
namespaceNamespace the workload runs in.
service_cluster_ipIn-cluster ClusterIP.
stage_service_cluster_ipsMap of ClusterIPs for stage-specific services.
service_external_ipExternal LoadBalancer IP (when a static IP is reserved).
service_urlURL to reach ClassicPress.
database_instance_nameCloud SQL instance name.
database_name / database_userApplication database name / user.
database_password_secretSecret Manager secret holding the DB password.
database_host / database_portDB endpoint (127.0.0.1 via the Auth Proxy) / port.
storage_bucketsCreated Cloud Storage buckets (including classicpress-uploads).
network_name / network_exists / regionsVPC network, presence, available regions.
container_image / container_registryDeployed image and Artifact Registry repo.
monitoring_enabled / monitoring_notification_channelsMonitoring status and channels.
initialization_jobs / db_import_jobNames of the setup (db-init) and (optional) import jobs.
deployment_id / tenant_id / resource_prefixNaming identifiers.
project_id / project_numberProject identifiers.
cicd_enabled / cicd_configurationCI/CD status and details (repo, trigger, registry).
github_repository_url / github_repository_owner / github_repository_nameCI/CD GitHub details.
artifact_registry_repository / cloudbuild_trigger_name / cloudbuild_trigger_idRegistry and build trigger.
kubernetes_readyWhether the cluster/workload is ready.
vpc_sc_enabled / vpc_sc_perimeter_name / vpc_sc_dry_run_modeVPC-SC status.
audit_logging_enabled / artifact_registry_cmek_enabledAudit logging and CMEK status.

6. Configuration Pitfalls & Sensible Defaults​

Risk: Critical (data loss / outage / security) — High (service degraded) — Medium (cost or partial degradation) — Low (minor).

Inherited plan-time validation. This module passes its configuration through the App_GKE foundation engine, which validates values and combinations at plan time — a StatefulSet forced alongside a stateless setting, IAP with no authorized identities, quota_memory_* given as bare integers, an out-of-range container_port/backup_retention_days. Invalid configuration fails the plan with a clear, named error before any resource is created, so most mistakes below are caught up front rather than at apply or runtime. ClassicPress also runs its own preconditions (validation.tf) for upload_max_filesize ≤ post_max_size, min_instance_count ≤ max_instance_count, Redis without a host source, IAP without OAuth credentials, and enable_cloudsql_volume with database_type = "NONE".

SettingSensible valueRiskConsequence if wrong
database_typenull (→ MYSQL_8_0)CriticalClassicPress_Common's db-init job and entrypoint are MySQL-specific; overriding to a Postgres/SQL Server engine breaks both.
application_database_name / application_database_userSet onceCriticalImmutable after first deploy; renaming recreates the DB/user and orphans all data.
CLASSICPRESS_SALT_SEED (auto-generated)Never changeCriticalChanging the seed after first boot invalidates all signed cookies and logged-in sessions.
stateful_pvc_size / stateful_pvc_mount_path10Gi / /var/www/htmlCriticalThis PVC holds the entire install (code + uploads) — resizing down or losing the PVC destroys the site; the mount path must match where ClassicPress's entrypoint writes.
max_instance_count1HighEach StatefulSet pod gets its own PVC; scaling beyond 1 gives every replica a separate, diverging copy of the site rather than a shared one.
enable_cloudsql_volumetrueHighThe Auth Proxy sidecar on 127.0.0.1:3306 is required for DB connectivity on GKE.
enable_nfstrueLowProvisions and pays for a Filestore instance mounted at /var/www/html/wp-content — the confirmed mechanism for upload/plugin/theme persistence (see Section 3), on top of the StatefulSet PVC's per-pod persistence for the rest of the webroot.
stateful_pvc_storage_classstandard-rwo (SSD)MediumDraws the tight regional SSD_TOTAL_GB quota. Override to standard (HDD pd-standard) on quota-constrained projects — fine for a low-IOPS PHP/MySQL workload.
First-run admin setupComplete /wp-admin/install.php promptly after deployMediumUntil the installer runs, the site has no schema and no admin account — there is no generated admin-password secret to recover with.
memory_limit2GiMediumBelow ~512Mi the PHP/Apache pod risks OOM under load or with heavier plugins.
quota_memory_requests / _limitsbinary units (4Gi, 8192Mi)CriticalBare integers are treated as bytes and block all pod scheduling in the namespace.
reserve_static_iptrueMediumWithout it, the external IP can change across redeploys, breaking DNS and any hardcoded site URL.
backup_retention_days7 (raise for prod)MediumToo short for compliance retention.

For the foundation behaviour referenced throughout — IAM and Workload Identity, autoscaling, ingress and certificates, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC-SC, backups, and image mirroring — see App_GKE. ClassicPress-specific application configuration shared with the Cloud Run variant is described in the ClassicPress_Common module (no standalone ClassicPress_Common.md guide exists yet in this docs set).

Need RAD to do something it does not do yet? Request it on the roadmap, or vote on what is already there.