Deployment Runbook: Staging (Legacy — Kubernetes/Helm)¶
SUPERSEDED - this is not the current staging path
This page describes the planned future Kubernetes/Helm/Terraform staging architecture, which remains on hold behind the domain-registration blocker documented below. It is kept for historical/future-architecture reference only - do not follow it to deploy or verify today's real staging environment.
VayzoMart's current, live staging environment runs on the shared-VPS Docker Compose
architecture instead, at https://stg.vayzomart.com. For the canonical, actually-used
runbook, see Deployment → Staging (VPS).
The two architectures are expected to coexist only until this Kubernetes path's own domain and infrastructure prerequisites are met, at which point a real migration decision (not a silent switch) will be made and this page updated accordingly.
Deployed automatically by Jenkins on every release-tag build (v*.*.*) - this page documents
what happens and how to reproduce/verify it manually; it is not a page this portal (or any
unattended process) executes deploys from.
⚠ Deployment is currently blocked - domain not yet registered¶
AkshayaBazaar's own public domain has not been registered yet. akshayathreadworld.in (the
hostname this runbook, the Helm chart, and the deployment scripts previously referenced) belongs
to a different, unrelated application and must never be used for AkshayaBazaar - not for DNS,
not for CORS, not for TLS, not even as a placeholder.
Every domain-shaped value in this repo (helm/akshayabazaar/values-staging.yaml, Jenkinsfile,
scripts/deploy-staging.ps1/.sh, scripts/verify-staging.ps1) now uses a clearly non-routable
RFC 2606 "reserved for documentation" placeholder - staging.akshayabazaar.example.invalid -
instead. This placeholder will never resolve, by design; it exists only so config files stay valid
and self-explanatory, not as something to actually deploy against.
Do not deploy to real staging until:
1. A real domain is registered for AkshayaBazaar, and
2. terraform/environments/staging/terraform.tfvars (and platform's) is filled in with that
real domain_name, and Terraform has actually provisioned the corresponding Cloudflare DNS
record, and
3. helm/akshayabazaar/values-staging.yaml's ingress.host/backend.config.allowedOrigins/
backend.config.fileStorage.baseUrl/backend.config.r2.publicBaseUrl are updated (or
overridden via --set) to that real hostname.
Until then, scripts/verify-staging.ps1 requires -IngressHost to be supplied explicitly (it no
longer defaults to any real-looking hostname) or -SkipExternalHttp to run the in-cluster checks
only - see that script's own header. scripts/deploy-staging.ps1/.sh will still deploy the
placeholder hostname if run as-is; the resulting Ingress will simply never be reachable from the
internet until the real domain is wired in, which is the intended, safe behavior in the meantime.
Preconditions¶
terraform/environments/platform/andterraform/environments/staging/already applied (see Terraform) - the shared K3s node and staging's own data VM must exist.environments/staging/kubernetes/namespace.yamlandenvironments/staging/kubernetes/deployer-rbac.yamlapplied by an operator after the cluster exists. Use the resulting namespace-scoped ServiceAccount token for the staging deploy kubeconfig; do not use K3s's raw cluster-admin kubeconfig for routine staging deploys. The namespace manifest is the canonical owner ofakshayabazaar-staging; real staging deploy scripts require the namespace to already exist and do not pass Helm--create-namespace.akshayabazaar-staging-secretsSecret already applied in theakshayabazaar-stagingnamespace.- Backend tests, frontend tests, and both dependency/image scans passed (Jenkins won't reach this stage otherwise - see CI/CD → Jenkins).
Scaling policy¶
Current HPA matrix:
| Environment | Backend | Frontend |
|---|---|---|
| staging | min 1 / max 2 | min 1 / max 2 |
| production | min 2 / max 6 | min 2 / max 4 |
Staging is intentionally conservative for cost and to avoid crowding production headroom on the shared K3s node. Production frontend and backend do not need identical limits: the backend is the CPU-bound API tier, while the frontend is lightweight nginx serving static assets.
Terraform validation¶
Safe, no-account checks before the Vayzo domain and account credentials exist:
cd terraform\environments\staging
terraform fmt -check -diff
terraform init -backend=false
terraform validate
Real planning, once manual account inputs are available:
Do not run terraform apply during readiness review. A real plan requires:
- Cloudflare account ID, zone ID, and scoped API token.
- R2 remote-state access key/secret and the real R2 backend endpoint replacing
ACCOUNT_ID. - Hetzner token and SSH/admin CIDR inputs.
terraform/environments/platform/already applied so staging can read the shared K3s node and network outputs.- The real Vayzo/AkshayaBazaar domain, with staging using a configurable subdomain rather than a hardcoded hostname.
Backup/checkpoint¶
Automated nightly backup, when backup.enabled: true - see
Operations → Backup. Before a specific risky release, a manual
checkpoint is reasonable:
# Linux/Bash, from a host that can reach staging's data VM
mysqldump -h <staging-data-vm-private-ip> -u <DB_USER> -p ecommerce_db > staging-pre-release-$(date +%Y%m%d).sql
Build¶
Jenkins builds both images once per commit (see CI/CD → Jenkins) - never rebuilt for staging specifically.
Deploy¶
$env:KUBECONFIG = "path\to\kubeconfig-staging.yaml"
.\scripts\deploy-staging.ps1 -ImageTag <commit-sha>
scripts/deploy-staging.ps1 and scripts/deploy-staging.sh (as well as Jenkins) enforce the canonical pre-deployment privacy gate (scripts/pre-deploy-gate.ps1 / scripts/pre-deploy-gate.sh) BEFORE executing helm upgrade --install. Direct, raw Helm commands against staging are strictly prohibited. The scripts set HELM_DRIVER=configmap so Helm release state lives in ConfigMaps; app, DB, R2, Razorpay, JWT, and backup Secrets remain pre-created outside Helm.
Database migration¶
Runs automatically as a Helm pre-upgrade hook, same as every environment - see Kubernetes → Helm → Migrations. Staging's migrations run against staging's own data VM only.
Verification¶
(namespace/release still default to real staging's;-IngressHost no longer defaults to any
real-looking hostname - see "Deployment is currently blocked" above. Until a real domain exists,
run .\scripts\verify-staging.ps1 -SkipExternalHttp instead, which verifies everything except the
external HTTP check.)
Expected result¶
Summary: 14 PASS, 0 WARNING, 0 FAIL - same target as local, against real infrastructure.
Smoke testing¶
Jenkins runs scripts/smoke-test.sh automatically immediately after deploy - a failure here stops
the pipeline before production promotion is ever offered.
Monitoring¶
See Operations → Monitoring for what's wired up versus documented-but-off.
Rollback¶
(dry run by default - printshelm history; add -Yes to actually roll back).
Both scripts/rollback-staging.ps1 -Yes and Jenkins (ACTION=Rollback, ROLLBACK_ENV=staging) enforce the canonical pre-deployment privacy gate before executing helm rollback. Direct, raw helm rollback commands are strictly prohibited. Full detail: Operations → Rollback.
Common failure scenarios¶
Same NetworkPolicy/migration-hook classes of failure as local (this cluster runs the identical chart) - see Kubernetes → Troubleshooting.