DevelopmentJune 13, 2026

How to self-host Plausible Analytics on Kubernetes

Have you ever felt like Google Analytics has turned into the control panel of an alien spaceship that no mere mortal can operate? And that neither you nor your client really need all those features that come bundled with a 50 KB JS script? Well, that's what happened to me, and that's why a few days ago I went looking around the web analytics market to see what other options were out there.

My criteria were:

  • simple traffic monitoring (who, from where, with what agent/device)
  • low price
  • lightweight
  • open source if possible
  • GDPR and CCPA compliance

If you'd gone down the same road as me, you'd have found there are plenty of options: Clicky, HubSpot, Mixpanel, Gauges, StatCounter, and a long etcetera. Going through that fairly long list, I realized most of them failed at least one of my requirements, whether because of price, the complexity of the service and a heavy script, or a dull and outdated UI/UX. Most of them, but not Plausible Analytics.

So the decision was made.

Plausible Analytics

Plausible Analytics web interface
Plausible Analytics web interface

Plausible Analytics is a web analytics service that offers simple metrics, a tiny script, a pleasant interface, transparency, and a lot of flexibility since the product is open source. It has strong arguments that convinced me almost instantly: it doesn't use cookies (which makes it fully compliant with the various cookie laws and privacy regulations), it's based in the EU and runs on renewable energy, and, above all, it lets you skip the cloud and self-host it without paying literally anything (although I'd recommend, at the very least, becoming a GitHub sponsor) if, like me, you already have some infrastructure set up.

A naive approach

So I went with self-hosting, with the idea of dropping a Plausible instance into the k8s cluster managed with Rancher. However, even though the documentation section explains how to get everything up and running on a server with Docker, it says nothing about the k8s case.

The first thing I did was follow the naive approach, with a single deployment based on the suggested plausible/analytics:latest image:

  • created a new plausible namespace
  • filled in the configuration with the required environment variables from plausible-conf.env
  • set up persistent storage with a bind mount to the previously created /data/user/plausible directory

No luck. The instance couldn't connect to the Postgres and Clickhouse databases that I assumed would already be there. That meant the Plausible image doesn't include everything: it only packages the product's core functionality, and the actual installation requires additional steps to set up the databases. Fine, nothing serious.

Next, I explored the repository. There I found two interesting things:

  • docker-compose.yml
  • the kubernetes folder

The compose file made it clear that the final setup included a Postgres database (plausible-db), a Clickhouse database (plausible-events-db), and Plausible Analytics itself (plausible), all deployed together. Here's a very basic diagram of the Plausible architecture I drew to better understand it:

Diagram of the Plausible Analytics architecture
Diagram of the Plausible Analytics architecture

You can find more information about the tech stack and how it works in Plausible's great development notes on their blog. I found Technology choices and the Building Plausible recaps from June 2019 and April 2020 especially interesting.

The kubernetes folder contained an unofficial extension of the documentation on how to run it locally with k8s, with a bunch of kubectl commands and all the useful yaml configurations for this case. Great.

An informed approach

After getting familiar with all the yaml files I mentioned and deleting the initial deployment, I was ready to get to work.

Setting up Postgres

I started with the Postgres database deployment. The setup was straightforward, since there was already a plausible-db.yaml. This is everything I did:

  • create a new deployment based on the postgres:latest image

  • set the container port to 5432

  • set up storage with a bind mount at the path /data/user/plausible/postgresql and mount point /var/lib/postgresql/data

  • add the required environment variables


    env:
    - name: POSTGRES_DB
    value: plausible
    - name: PGDATA
    value: /var/lib/postgresql/data/pgdata
    - name: POSTGRES_USER
    value: user
    - name: POSTGRES_PASSWORD
    value: password

  • set up a ClusterIP type service discovery, from port 5432 to 5432 with TCP protocol, following the configuration

And that was basically it; I left the rest of the settings at their defaults. The Postgres instance started up without any issues.

Setting up Clickhouse

Next up was the Clickhouse database, whose setup is very similar to the previous one, so I won't bore you by repeating it. Here's the plausible-events-db.yaml, which says it all.

The only notable difference is the addition of a ConfigMap:


apiVersion: v1
kind: ConfigMap
metadata:
name: plausible-events-db-config
data:
clickhouse-config.xml: |
<yandex>
<logger>
<level>warning</level>
<console>true</console>
</logger>
{/* Stop all the unnecessary logging */}
<query_thread_log remove="remove"/>
<query_log remove="remove"/>
<text_log remove="remove"/>
<trace_log remove="remove"/>
<metric_log remove="remove"/>
<asynchronous_metric_log remove="remove"/>
</yandex>
clickhouse-user-config.xml: |
<yandex>
<profiles>
<default>
<log_queries>0</log_queries>
<log_query_threads>0</log_query_threads>
</default>
</profiles>
</yandex>

This is a small Clickhouse optimization. If you're curious what it's for, take a look at this commit

And then it gets added alongside the bind-mount volumes, like this:


volumeMounts:
- name: data
mountPath: /var/lib/clickhouse
- name: config
mountPath: /etc/clickhouse-server/config.d/logging.xml
subPath: clickhouse-config.xml
readOnly: true
- name: config
mountPath: /etc/clickhouse-server/users.d/logging.xml"
subPath: clickhouse-user-config.xml
readOnly: true

Add another service discovery and that's it: you now have a Clickhouse database instance.

Setting up Plausible

The last big task was setting up Plausible itself. Same story: I took the plausible.yaml and repeated the previous steps. That said, with two notes:

  1. There need to be two containers, one of them an init type, which runs before the main container to prepare the databases and trigger the migration with the following command:

initContainers:
- name: plausible-init
image: plausible/analytics:latest
command:
- '/bin/sh'
- '-c'
args:
- sleep 30 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh db init-admin

Then the regular container runs.

  1. Make sure to fill in the required variables correctly. Check the configuration page to learn more about them.

// postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@$(PLAUSIBLE_DB_SERVICE_HOST):$(PLAUSIBLE_DB_SERVICE_PORT)/plausible
DATABASE_URL=postgres://user:password@plausible-db.plausible:5432/plausible
// http://$(CLICKHOUSE_USER):$(CLICKHOUSE_PASSWORD)@$(PLAUSIBLE_EVENTS_DB_SERVICE_HOST):$(PLAUSIBLE_EVENTS_DB_SERVICE_PORT)/plausible
CLICKHOUSE_DATABASE_URL=http://user:password@plausible-events-db.plausible:8123/plausible
ADMIN_USER_EMAIL=user@mail.com
ADMIN_USER_NAME=user
ADMIN_USER_PWD=password
// notice the protocol
BASE_URL=https://plausible.example.com
// generate one by running "openssl rand -base64 64 | tr -d '\n'" in your terminal
SECRET_KEY_BASE=

Then you add one more service discovery and everything should work smoothly. There's just one small detail left.

Setting up the reverse proxy

The documentation says:

By default, Plausible runs over unencrypted HTTP on port 8000. We recommend running it with HTTPS behind some kind of reverse proxy.

That seemed reasonable, so in the Cloudflare dashboard I set up a simple A record with the node's IP address, went back to Rancher, and added an Ingress configuration to expose my brand-new Plausible instance to the outside world.

The login screen finally showed up on my trusty secure domain. Mission accomplished.

Plausible Analytics login page
Plausible Analytics login page

And that's it!

This has been my experience self-hosting Plausible Analytics on k8s. Even though there are fairly clear hints on how to do it, it's not obvious, and that's exactly why I wrote this article. I hope it's useful to you.

The Plausible team maintains the product as open source and supports the self-hosted version, including instructions for Kubernetes, which makes the installation a lot easier.

Tell us about your case

Get in touch