Self-hosting website analytics often requires complex orchestration of separate transactional and analytical databases. This configuration deploys Plausible CE on Kubernetes with PostgreSQL for operational data and ClickHouse for analytics events, producing a GDPR-compliant, cookie-free analytics stack accessible at a local domain.
What's Included
| Component | Type | Port | Role |
|---|---|---|---|
plausible | Namespace | - | Isolates all resources under plausible |
plausible-pg-pvc | PersistentVolumeClaim | - | 10 GB for PostgreSQL data |
plausible-ch-pvc | PersistentVolumeClaim | - | 20 GB for ClickHouse events |
plausible-pg-config | ConfigMap | - | PostgreSQL env vars |
plausible-pg-secret | Secret | - | PostgreSQL password |
plausible-ch-config | ConfigMap | - | ClickHouse env vars |
plausible-ch-secret | Secret | - | ClickHouse password |
plausible-ch-files | ConfigMap | - | config.xml and users.xml as mounted files |
plausible-app-config | ConfigMap | - | Plausible env vars (BASE_URL, DB URLs) |
plausible-app-secret | Secret | - | SECRET_KEY_BASE |
plausible-postgres | StatefulSet | 5432 | PostgreSQL 16: OLTP store for users and config |
plausible-postgres-service | Service (ClusterIP) | 5432 | Internal DNS only |
plausible-clickhouse | Deployment | 8123/9000 | ClickHouse: OLAP store for events |
plausible-clickhouse-service | Service (ClusterIP) | 8123/9000 | Internal DNS only |
plausible | Deployment | 8000 | App server with 3 init containers |
plausible-service | Service (ClusterIP) | 8000 | Internal: Ingress routes here |
nginx | IngressClass | - | Declares NGINX as default ingress class |
plausible-ingress | Ingress | 80 | Routes plausible.local to app service |
plausible-hpa | HorizontalPodAutoscaler | - | Scales Plausible pods from 1 to 3 replicas |
plausible-quota | ResourceQuota | - | Namespace resource cap |
plausible-limits | LimitRange | - | Per-container defaults |
plausible-postgres-netpol | NetworkPolicy | 5432 | PostgreSQL: Plausible pods only |
plausible-clickhouse-netpol | NetworkPolicy | 8123/9000 | ClickHouse: Plausible pods only |
plausible-app-netpol | NetworkPolicy | 8000 | Plausible: NGINX ingress only |
Architecture Overview
PostgreSQL stores users, sites, and goals, while ClickHouse stores every pageview for fast aggregation. The Plausible pod is the only component that talks to both databases, a constraint enforced by NetworkPolicies. Three sequential init containers ensure both databases are ready and migrations complete before the main application starts. NGINX Ingress forwards real client IPs for accurate geo data parsing.
Prerequisites
- NGINX Ingress Controller deployed in the ingress-nginx namespace
- 6 GB RAM available to the cluster node
- 127.0.0.1 plausible.local added to your hosts file
- KubeKanvas CLI installed and running on your computer (Optional, if you want to use one-click deployment)
How to Deploy
- Confirm the NGINX Ingress Controller is running in the ingress-nginx namespace.
- Generate a SECRET_KEY_BASE value using
openssl rand -hex 64, base64-encode it, and replace the placeholder in the plausible-app-secret manifest. - Update the storage paths in both PVCs to match your operating system filesystem structure.
- Deploy the template to your cluster via the Play button in the top right bar. If you prefer to deploy manually, download the YAML and apply it with kubectl.
- Wait for all pods to reach Running status. You can monitor progress in the Release Monitor screen.
How to Test
- Run
kubectl get pods -n plausibleand confirm all three pods show a status of Running. - Open
http://plausible.localin your browser and confirm the Plausible admin setup screen loads. - Create your admin account, add a test site, and confirm the analytics dashboard renders.
- Execute an HTTP GET request against
http://plausible.local/api/healthand confirm the JSON response shows healthy.
Use Cases
- Privacy-first analytics: Replace Google Analytics with a cookie-free, GDPR-compliant alternative where all data stays on your own infrastructure.
- Air-gapped deployments: Run an analytics platform that requires no external internet access to record or display traffic data once deployed.
- Multi-site tracking: Aggregating multiple tracking scripts into one instance using isolated dashboards and goals.
- High-volume event storage: Scale from a personal blog to a high-traffic site using ClickHouse as an analytical data store without changing the architecture.
Summary
This template configures a 24-resource Kubernetes stack running Plausible CE with PostgreSQL for operational data and ClickHouse for analytics events, exposed via NGINX Ingress with per-component ConfigMap, Secret, and NetworkPolicy isolation.
