Self-hosting analytics using Plausible, Docker and Caddy

⚠️
This post is written based on my experience before the Plausible Community Edition was announced. Most of it should still be relevant and applicable; I'll remove this notice once I've had a chance to update my Plausible instance. Just waiting for the final 2.1.0 version to be released!

In a previous post I described how relatively straight-forward it was to set up this site using Ghost behind Caddy.

To build on that setup, I wanted to explore self-hosting analytics. I'd been eyeing Plausible for a while – Google Analytics was just too bloated (not to mention ignored by almost all ad blockers / privacy tools), Cloudflare web analytics was decent but pretty limited in functionality (actually I just discovered this post by one of Plausible's founders, illuminating!)

Getting Plausible up and running locally with Docker was pretty simple, mostly just followed the instructions here. Here's my Docker compose file, relevant changes are annotated:

version: "3.3"
services:
  plausible_db:
  # I removed bytemark/smtp since I'm using mailgun for email
version: "3.3"
services:
  plausible_db:
    # I updated to Postgres 15, works fine!
    image: postgres:15-alpine
    restart: always
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=<replace me>
  # no changes here
  plausible_events_db:
    image: clickhouse/clickhouse-server:23.3.7.5-alpine
    restart: always
    volumes:
      - event-data:/var/lib/clickhouse
      - ./clickhouse/clickhouse-config.xml:/etc/clickhouse-server/config.d/logging.xml:ro
      - ./clickhouse/clickhouse-user-config.xml:/etc/clickhouse-server/users.d/logging.xml:ro
    ulimits:
      nofile:
        soft: 262144
        hard: 262144

  plausible:
    image: plausible/analytics:v2.0
    restart: always
    command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
    depends_on:
      - plausible_db
      - plausible_events_db
        # removed `mail` as I'm using mailgun
    ports:
      # default was `8000:8000` -- below worked for me with Caddy
      - 127.0.0.1:8002:8000
    env_file:
      - plausible-conf.env

volumes:
  db-data:
    driver: local
  event-data:
    driver: local
  geoip:
    driver: local

Here's my env file:

BASE_URL=https://analytics.diwaker.io
SECRET_KEY_BASE=<replace me>
MAILER_ADAPTER=Bamboo.MailgunAdapter
MAILGUN_API_KEY=<replace me>
MAILGUN_DOMAIN=<replace me>
ENABLE_EMAIL_VERIFICATION=true

Then run docker compose up and the containers should spin up! All that remains is hooking it up to Caddy. Here's the relevant bit from my Caddyfile:

analytics.diwaker.io {
        reverse_proxy localhost:8002
}

That's it!