Some might say, Google is some kind of villain. Not only because of the company’s privacy-invading tactics or the use of cookies. But did you ever try to find a key metric in the Analytics-Dashboard? Its easy to sink hours and hours into their »properties« or »key-value-pairs« or whatever they name the Json-Datapoints next. So we went to look for alternatives. And – spoiler alert: we found something …
Plausible Heroes
Unlike Google, our hero is called Plausible. Plausible is privacy-friendly, lightweight and yes: open-source. But it gets even better: like our website, Plausible does not use cookies. The tool is also compliant with applicable data protection regulations such as GDPR, CCPA and PECR. Plausible’s servers are located in the EU. But best of all, Plausible allows us to operate our own statistics server. There’s also a dark mode. So it ticks all the right boxes. And that’s not a generic catchphrase made up by an AI. It. Is. True.
Why doesn’t everyone use this?
Because installing and maintaining a statistics server means work, of course. But work on the part of the administrator. With Google, on the other hand, the work lies with the users.
How cool is this?
So cool:

I want to host this myself
Okay. That’s why we’ve put together a little bit of information on how to do this. However, this requires a little basic knowledge of containers. So if you have experience with Docker or Kubernetes and you download images from Github as if it were an app store for server stories, then you’ve come to the right place.
Installation
In general, Plausible consists of three containers. The database that stores the values of the individual websites is a Clickhouse cluster. The settings of the Plausible dashboard, on the other hand, are stored in a Postgres database. And last but not least, there is the Plausible container itself. It is connected to the two databases and has a fourth, optional container that is responsible for weekly mails.
Clickhouse Deployment
Our Clickhouse installation looks roughly like this:
apiVersion: apps/v1
kind: Deployment
metadata:
name: clickhouse
namespace: web
spec:
replicas: 1
selector:
matchLabels:
app: clickhouse
template:
metadata:
labels:
app: clickhouse
spec:
containers:
- name: clickhouse
image: clickhouse/clickhouse-server:24.12.2.29-alpine
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 8123
envFrom:
- secretRef:
name: clickhouse-secret
volumeMounts:
- mountPath: /var/lib/clickhouse
name: plausible-clickhouse-data
resources:
limits:
cpu: 600m
memory: 4Gi
requests:
cpu: 300m
memory: 2Gi
volumes:
- name: plausible-clickhouse-data
persistentVolumeClaim:
claimName: plausible-clickhouse-data The database must persist data, i.e. write it permanently to a hard drive. To do this, we have created a so-called PV with the name plausible-clickhouse-data. We link this to the container.
The database also needs a user and passwords. In Kubernetes, it is common practice to store access data in secrets. Our secret is therefore a file containing the following information:
apiVersion: v1
kind: Secret
metadata:
name: clickhouse-secret
namespace: web
type: Opaque
stringData:
CLICKHOUSE_DB: plausible_events_db
CLICKHOUSE_USER: username
CLICKHOUSE_PASSWORD: passwordThe secret is linked to the Clickhouse container via an environment variable. We specify another service so that Plausible can access the statistics database, i.e. Clickhouse:
apiVersion: v1
kind: Service
metadata:
name: clickhouse
namespace: web
labels:
app: clickhouse
spec:
ports:
- port: 8123
selector:
app: clickhouseThe port number 8123 is specified in the container and in the service. And that is actually the entire installation of Clickhouse.
Plausible Deployment
Our deployment for Plausible itself looks like this:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: plausible
namespace: web
spec:
replicas: 1
selector:
matchLabels:
app: plausible
template:
metadata:
labels:
app: plausible
spec:
- name: plausible-migrate
image: ghcr.io/plausible/community-edition:v2.1.5
command:
- '/bin/sh'
- '-c'
args:
# Uncomment first line for initial deployment and then switch
# - 'sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run'
# - '/entrypoint.sh db migrate'
envFrom:
- secretRef:
name: plausible-config
containers:
- name: plausible
image: ghcr.io/plausible/community-edition:v2.1.5
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 8000
envFrom:
- secretRef:
name: plausible-config
- name: mail
image: bytemark/smtp
imagePullPolicy: "IfNotPresent"
envFrom:
- secretRef:
name: plausible-configThe database must be created during the initial installation. Therefore you give the container the command 'sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run'. However, this is only necessary for the initial installation. After you have created the database, you can delete the previous command and instead enter: '/entrypoint.sh db migrate'.
The last lines in the manifest describe the mail container, which uses bytemark/smtp as the image. It is optional and can also be omitted. In this case, you will not have the option of sending weekly update mails automatically.
Our two Plausible containers also require various settings and credentials. The secret file looks like this:
apiVersion: v1
kind: Secret
metadata:
name: plausible-config
namespace: web
type: Opaque
stringData:
CLICKHOUSE_DATABASE_URL: http://username:password@clickhouse.web.svc.cluster.local:8123/plausible_events_db
DATABASE_URL: postgresql://plausible:password@postgres.web.svc.cluster.local/plausible
BASE_URL: https://statistics.example.com
SMTP_HOST_ADDR: smtp.example.com
SMTP_HOST_PORT: "587"
CRON_ENABLED: "true"
LOG_LEVEL: info
DISABLE_REGISTRATION: invite_only
ENABLE_EMAIL_VERIFICATION: "true"
TOTP_VAULT_KEY: abc12345678912345678912345678912345678912345
MAILER_EMAIL: hello@example.com
MAILER_NAME: Hello
SMTP_USER_PWD: password
SMTP_USER_NAME: user@example.comWith CLICKHOUSE_DATABASE_URL we tell Plausible where to find the Clickhouse database.
DATABASE_URL is the same for the Postgres database. Base-Url corresponds to the Url where your statistics server should be accessible.
You set CRON_ENABLED to true so that the server can perform recurring tasks, such as a weekly info mail.
Then add a few passwords - including for your mail server - and you’re done.
Now we just need a service that points to port 8000 so that you can access the Plausible app via the browser. In our case, the service looks like this:
apiVersion: v1
kind: Service
metadata:
name: plausible
namespace: web
labels:
app: plausible
spec:
ports:
- port: 8000
selector:
app: plausiblePostgres Deployment
You have several options for deploying Postgres. However, you probably already have the database running in your stack anyway. If not, we recommend using the Bitnami deployment. With or without a helmet. You can find out exactly how to do this here.
Test
Your statistics server should now be accessible under the IP address of your server on port 8000, i.e. http://192.168.1.2:8000.
Branding
Plausible also offers the option of integrating the dashboard on your own site without branding. How great is this? So great.
Outro
Okay. To be honest, it’s a bit of work to set up a statistics server like this. But yes. At Lightwaves, you can simply add Plausible to your website package. Then we take care of the complicated installation and maintenance. And you’ll have the most privacy-friendly analytics server in the world.
That is why we vote for Plausible - your users will appreciate it too.

