Deploy Production Volto Example¶
This guide shows you how to deploy the production-ready Volto example to your Kubernetes cluster.
What You’ll Deploy¶
The Production Volto example includes:
Plone 6.1 with Volto (React frontend + REST API backend)
PostgreSQL with RelStorage (CloudNativePG or Bitnami)
Varnish HTTP caching with kube-httpcache
Ingress with TLS (Traefik or Kong)
Three access domains (cached, uncached, maintenance)
Prerequisites¶
Required¶
Ensure you have these installed on your cluster:
Ingress Controller - Either:
Traefik v3 with CRDs
cert-manager - For TLS certificates:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yamlkube-httpcache Operator - For Varnish caching:
kubectl apply -f https://github.com/mittwald/kube-httpcache/releases/latest/download/kube-httpcache.yamlPostgreSQL Operator - Choose one:
Option A: CloudNativePG (recommended for production):
kubectl apply -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.24/releases/cnpg-1.24.0.yamlOption B: Bitnami (simpler for testing):
kubectl create namespace plone
Local Tools¶
Node.js 18+ and npm
kubectl configured for your cluster
git to clone the repository
Step 1: Get the Example¶
Clone the repository and navigate to the example:
git clone https://github.com/bluedynamics/cdk8s-plone.git
cd cdk8s-plone/examples/production-volto
Step 2: Install Dependencies¶
npm install
Step 3: Import CRDs¶
Generate TypeScript bindings for Kubernetes CRDs:
npm run import
This imports:
Kubernetes core API
CloudNativePG Cluster CRDs
Traefik Middleware CRDs
Step 4: Configure Environment¶
Create a .env file from the example:
cp .env.example .env
Edit .env with your settings:
# Your domains
DOMAIN_CACHED=plone.example.com
DOMAIN_UNCACHED=plone-test.example.com
DOMAIN_MAINTENANCE=plone-admin.example.com
# Your cert-manager ClusterIssuer
CLUSTER_ISSUER=letsencrypt-prod
# Optional: Custom images
#PLONE_BACKEND_IMAGE=plone/plone-backend:6.1.3
#PLONE_FRONTEND_IMAGE=plone/plone-frontend:latest
# Database: 'bitnami' or 'cloudnativepg'
DATABASE=cloudnativepg
Tip
For production, use cloudnativepg for high availability. For testing, bitnami is simpler.
Step 5: Generate Manifests¶
Synthesize Kubernetes YAML:
npm run synth
This creates dist/plone-example.k8s.yaml with all resources.
Step 6: Review Generated Manifests¶
Inspect what will be deployed:
# Count resources
grep "^kind:" dist/plone-example.k8s.yaml | sort | uniq -c
# View specific resources
kubectl apply --dry-run=client -f dist/plone-example.k8s.yaml
Step 7: Deploy to Kubernetes¶
Deploy to your cluster:
kubectl apply -f dist/plone-example.k8s.yaml
Or deploy to a specific namespace:
kubectl apply -f dist/plone-example.k8s.yaml -n plone
Step 8: Monitor Deployment¶
Watch pods starting:
# Watch all pods
kubectl get pods -l app.kubernetes.io/part-of=plone -w
# Check specific components
kubectl get pods -l app.kubernetes.io/name=plone-backend
kubectl get pods -l app.kubernetes.io/name=plone-frontend
kubectl get pods -l app.kubernetes.io/name=plone-httpcache
Wait for all pods to be Running:
kubectl wait --for=condition=ready pod -l app.kubernetes.io/part-of=plone --timeout=300s
Step 9: Verify Services¶
Check that services are created:
kubectl get svc -l app.kubernetes.io/part-of=plone
You should see:
plone-backend(backend service)plone-frontend(frontend service)plone-httpcache(Varnish cache)Database service (Bitnami or CloudNativePG)
Step 10: Check Ingress¶
Verify ingress routes:
kubectl get ingress
Check TLS certificates:
kubectl get certificate
Step 11: Access Your Site¶
Once DNS is configured and TLS certificates are issued:
Public site (cached): https://plone.example.com
Testing (uncached): https://plone-test.example.com
Maintenance: https://plone-admin.example.com
Create Plone Site¶
On first access to the maintenance domain:
Go to: https://plone-admin.example.com
Click “Create a new Plone site”
Fill in:
Site ID:
PloneTitle: Your site title
Language: Choose language
Click “Create Plone Site”
Troubleshooting¶
Pods Not Starting¶
Check pod logs:
# Backend logs
kubectl logs -l app.kubernetes.io/name=plone-backend -f
# Frontend logs
kubectl logs -l app.kubernetes.io/name=plone-frontend -f
# Database logs (CloudNativePG)
kubectl logs -l postgresql=plone-postgresql -f
Database Connection Issues¶
CloudNativePG:
# Check cluster status
kubectl get cluster
# Check secret
kubectl get secret -l cnpg.io/cluster
Bitnami:
# Check service
kubectl get svc -l app.kubernetes.io/name=postgresql
# Check secret
kubectl describe secret <postgresql-secret-name>
TLS Certificate Issues¶
# Check certificate status
kubectl describe certificate
# Check cert-manager logs
kubectl logs -n cert-manager deployment/cert-manager
Varnish Cache Not Working¶
# Check httpcache logs
kubectl logs -l app.kubernetes.io/name=plone-httpcache
# Check if kube-httpcache operator is running
kubectl get pods -n kube-httpcache-system
Updating Your Deployment¶
After making changes to the example:
Edit configuration files
Regenerate manifests:
npm run synthApply changes:
kubectl apply -f dist/plone-example.k8s.yaml
Scaling¶
Scale replicas by editing main.ts:
const plone = new Plone(this, 'plone', {
backend: {
replicas: 3, // Scale backend
},
frontend: {
replicas: 3, // Scale frontend
},
})
Then regenerate and reapply.
Cleanup¶
Remove all resources:
kubectl delete -f dist/plone-example.k8s.yaml
Next Steps¶
Configure monitoring and metrics
Set up backups for CloudNativePG
Customize Varnish caching rules
Review security best practices
See Also¶
Deploy Classic UI Example - For traditional Plone interface
Setup Prerequisites - Detailed cluster setup
Configuration Options - API reference