Privacy-focused analytics tools like Plausible are becoming increasingly popular as companies and individuals prioritize data sovereignty and privacy. Plausible Analytics is a lightweight, open-source, privacy-friendly alternative to Google Analytics. Hosting it yourself ensures that your analytics data remains entirely within your control, keeping your information secure and private.
The Plausible.io logo
There are good reasons to host Plausible locally on your own infrastructure:
Additionally, with Plausible you get:
If these benefits appeal to you, let’s dive into the setup process.
This guide provides a minimal example of how to set up Plausible Analytics using Docker Compose and Traefik. This is not a general guide on Docker Compose or Traefik, so basic familiarity with these tools is assumed. If you prefer using Nginx or other web proxies, adapting this setup should be straightforward.
Before proceeding, ensure you have the following:
The following example docker-compose.yml
file provides a basic setup for running Plausible with Traefik. It utilizes Docker labels to handle routing and SSL certificate generation - and requires a .env-file in the same directory as the docker-compose.yml
.
plausible_db:
image: postgres:16-alpine
restart: always
volumes:
- ${DATA_DIR}/plausible/db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- TZ=${DOCKER_TZ}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
start_period: 1m
plausible_events_db:
image: clickhouse/clickhouse-server:24.3.3.102-alpine
restart: always
volumes:
- ${DATA_DIR}/plausible/event-data:/var/lib/clickhouse
- ${DATA_DIR}/plausible/event-logs:/var/log/clickhouse-server
- ${CONFIG_DIR}/plausible/logs.xml:/etc/clickhouse-server/config.d/logs.xml:ro
- ${CONFIG_DIR}/plausible/ipv4-only.xml:/etc/clickhouse-server/config.d/ipv4-only.xml:ro
- ${CONFIG_DIR}/plausible/low-resources.xml:/etc/clickhouse-server/config.d/low-resources.xml:ro
- ${CONFIG_DIR}/plausible/override-config.xml:/etc/clickhouse-server/config.d/override-config.xml:ro
ulimits:
nofile:
soft: 262144
hard: 262144
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 -O - http://127.0.0.1:8123/ping || exit 1"]
start_period: 1m
environment:
- TZ=${DOCKER_TZ}
plausible:
image: ghcr.io/plausible/community-edition:v2.1.4
restart: always
command: sh -c "/entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
container_name: plausible
depends_on:
plausible_db:
condition: service_healthy
plausible_events_db:
condition: service_healthy
volumes:
- ${DATA_DIR}/plausible/data:/var/lib/plausible
ulimits:
nofile:
soft: 65535
hard: 65535
ports:
- "8000:8000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.plausible.rule=Host(`${PLAUSIBLE_DOMAIN}`)"
- "traefik.http.routers.plausible.entrypoints=web,websecure"
- "traefik.http.routers.plausible.tls.certresolver=zerosslCloudflare"
- "traefik.http.routers.plausible.tls.domains[0].main=${PLAUSIBLE_DOMAIN}"
environment:
- TMPDIR=/var/lib/plausible/tmp
- BASE_URL=https://${PLAUSIBLE_DOMAIN}
- SECRET_KEY_BASE=${PLAUSIBLE_SECRET_KEY_BASE}
- DATABASE_URL=postgres://postgres:${POSTGRES_PASSWORD}@plausible_db:5432/plausible_db
- GOOGLE_CLIENT_ID=${PLAUSIBLE_GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET=${PLAUSIBLE_GOOGLE_CLIENT_SECRET}
- MAILER_EMAIL=${PLAUSIBLE_SENDER_EMAIL}
- MAILER_NAME=${PLAUSIBLE_SENDER_NAME}
- SMTP_HOST_ADDR=${PLAUSIBLE_SMTP_HOST}
- SMTP_HOST_PORT=${PLAUSIBLE_SMTP_PORT}
- SMTP_USER_NAME=${PLAUSIBLE_SMTP_USERNAME}
- SMTP_USER_PWD=${PLAUSIBLE_SMTP_PASSWORD}
- TZ=${DOCKER_TZ}
This setup consists of three primary components:
postgres
).docker-compose.yml
—update it within PostgreSQL first.${CONFIG_DIR}/plausible/
.For the above setup to work, you need to do some additional configuration.
You need to make sure you have a TLS enabled SMTP server that accepts connections from your server. Plausible doesn't send a lot of emails. For a simple and low cost solution, check out Option 2: Send email with the Gmail SMTP server at Google support, which will work fine for most cases as long as you accept that the sending email is a Gmail account.
The GOOGLE_CLIENT_ID and the GOOGLE_CLIENT_SECRET are needed to make the Google integrations work. But how you do get these values? There is a brilliant walktrough here. It will help you with setting up both the data migration and the search console integration.
When setting up the directory structure for Clickhouse and the Postgres database, make sure the directory permissions are correct. The original Plausible documentation doesn't use bind mounts as I do; instead they use docker volumes. When using bind mounts, you get better visibility to the files, but there are other disadvantages, so you should consider using docker volumes for a production environment. If you use bind mounts, make sure that:
db
directory is owned by uid 70 (chown 70:root -R db)data
directory is owned by uid 999 (chown 999:nogroup -R data)event-data
and event-logs
are owned by syslog (chown syslog:crontasb -R event-data and event-logs)If permissions are wrong, you may get stuck in a reboot loop because the database is never properly created, and you may get strange "timezone" warnings because Plausible can't create a timezone directory within the data
directory as part of the bootstrapping process.
The correct permission settings may differ, but this is what worked for me. If you have problems with the installation not finishing - just use docker volumes. Just make sure you back up the volumes securely.
By running Plausible behind Traefik, you gain insightful analytics while maintaining complete control over your data. This setup ensures privacy, flexibility, and security, making it an excellent alternative to third-party analytics providers.