Run Plausible With Docker Swarm & Traefik
I can't praise Plausible enough. It's a truly great product. While the self-hosted installation docs are useful if you're using Docker Compose, they don't go into any details about how to run it with Docker Swarm, hence the reason for this blog post.
Firstly it's good to be aware the following points:
- At the time of writing, Plausible (well, mainly Clickhouse) does not support the arm64 architecture, so if you're trying to run Plausible on a Raspberry Pi or a fancy M1 Mac, you're going to have a bad time. (But you can always build the images yourself.)
-
At the time of writing, we have to use a non-stable version of
Plausible to utilise a recent change to read config from file
(to support Docker Secrets).
- (Note that I fixed a bug relating to reading config from file.)
Now to set things up.
First let's define our stack definition:
version: '3.8'
services:
plausible_db:
image: postgres:13.3-alpine
volumes:
- plausible-db-data:/var/lib/postgresql/data
networks:
- plausible
healthcheck:
test: ['CMD', 'pg_isready']
environment:
- POSTGRES_DB=plausible
- POSTGRES_USER_FILE=/run/secrets/plausible-postgres-user
- POSTGRES_PASSWORD_FILE=/run/secrets/plausible-postgres-password
secrets:
- plausible-postgres-password
- plausible-postgres-user
deploy:
mode: replicated
replicas: 1
labels:
- 'traefik.enable=false'
plausible_events_db:
image: yandex/clickhouse-server:21.3.2.5
volumes:
- plausible-event-data:/var/lib/clickhouse
- plausible-etc-clickhouse-server:/etc/clickhouse-server
networks:
- plausible
deploy:
mode: replicated
replicas: 1
labels:
- 'traefik.enable=false'
plausible:
image: plausible/analytics:master@sha256:adfc5f693e8d70d48b04fc17b009b2871b9ee23d9a349e606eab708e964d2a60
command: sh -c "/entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh db init-admin && /entrypoint.sh run"
networks:
- plausible
- traefik-public
environment:
- CONFIG_DIR=/run/secrets
- SMTP_HOST_PORT=587
healthcheck:
test:
['CMD', 'wget', '-q', '--tries=1', '--spider', 'http://localhost:8000']
secrets:
- source: plausible-admin-user-email
target: /run/secrets/ADMIN_USER_EMAIL
- source: plausible-admin-user-name
target: /run/secrets/ADMIN_USER_NAME
- source: plausible-admin-user-password
target: /run/secrets/ADMIN_USER_PWD
- source: plausible-base-url
target: /run/secrets/BASE_URL
- source: plausible-secret-key-base
target: /run/secrets/SECRET_KEY_BASE
- source: plausible-database-url
target: /run/secrets/DATABASE_URL
- source: plausible-mailer-email
target: /run/secrets/MAILER_EMAIL
- source: plausible-smtp-host-addr
target: /run/secrets/SMTP_HOST_ADDR
- source: plausible-smtp-user-name
target: /run/secrets/SMTP_USER_NAME
- source: plausible-smtp-user-pwd
target: /run/secrets/SMTP_USER_PWD
- source: plausible-google-client-id
target: /run/secrets/GOOGLE_CLIENT_ID
- source: plausible-google-client-secret
target: /run/secrets/GOOGLE_CLIENT_SECRET
deploy:
mode: replicated
replicas: 1
labels:
- 'traefik.enable=true'
- 'traefik.docker.lbswarm=true'
- 'traefik.http.routers.plausible.entrypoints=web'
- 'traefik.http.routers.plausible.rule=Host(`plausible.example.com`)'
- 'traefik.http.services.plausible-service.loadbalancer.server.port=8000'
- 'traefik.http.middlewares.plausible-redirectscheme.redirectscheme.permanent=true'
- 'traefik.http.middlewares.plausible-redirectscheme.redirectscheme.scheme=https'
- 'traefik.http.routers.plausible.middlewares=plausible-redirectscheme'
- 'traefik.http.routers.plausible-secure.entrypoints=websecure'
- 'traefik.http.routers.plausible-secure.rule=Host(`plausible.example.com`)'
- 'traefik.http.routers.plausible-secure.tls.certresolver=letsencrypt'
networks:
traefik-public:
external: true
plausible:
driver: overlay
attachable: true
secrets:
plausible-admin-user-email:
external: true
plausible-admin-user-name:
external: true
plausible-admin-user-password:
external: true
plausible-base-url:
external: true
plausible-secret-key-base:
external: true
plausible-postgres-user:
external: true
plausible-postgres-password:
external: true
plausible-database-url:
external: true
plausible-geoupdate-account-id:
external: true
plausible-geoupdate-license-key:
external: true
plausible-mailer-email:
external: true
plausible-smtp-host-addr:
external: true
plausible-smtp-user-name:
external: true
plausible-smtp-user-pwd:
external: true
plausible-google-client-id:
external: true
plausible-google-client-secret:
external: true
volumes:
plausible-db-data:
plausible-event-data:
plausible-etc-clickhouse-server:
If you've worked with Docker Swarm & Traefik before, the above stack definition should be familiar to you, but here's some things to keep in mind:
- You need to manually create the Docker Secrets (I use Portainer to create secrets using a GUI).
-
I've pinned Plausible to version
plausible/analytics:master@sha256:adfc5f693e8d70d48b04fc17b009b2871b9ee23d9a349e606eab708e964d2a60
(which is the change that contains the fix to read config from file). -
Plausible reads config from disk that corresponds to the config
name (eg
GOOGLE_CLIENT_SECRET
), but I don't want to name my secrets like this (as secrets are global), which is why we're mounting the secrets under different names. - We're using Traefik for network routing and SSL termination.
(If you're looking for a handy script to setup Portainer, Traefik & Docker swarm on a small VPS, check out docker box.)
Hopefully you found this article useful. Any questions? Leave a comment below!
(No comments)