Skip to content

TutorialsAnalytics

How to install Plausible Community Edition with Docker Compose

Self-host Plausible Analytics Community Edition with Docker Compose, PostgreSQL and ClickHouse behind Caddy HTTPS, set up email, back up both databases.

  • Intermediate
  • 40 min read
  • Updated

Tested on: Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12, Debian 13

This guide is not available in your language yet, so it is shown in English.

On this page
  1. Prerequisites
  2. Step 1 — Check the CPU and install git
  3. Step 2 — Clone the current release
  4. Step 3 — Create the .env file
  5. Step 4 — Publish Plausible on the loopback address
  6. Step 5 — Serve Plausible over HTTPS with Caddy
  7. Step 6 — Create your account and add a site
  8. Step 7 — Configure email
  9. Back up and restore
  10. Update Plausible CE
  11. Troubleshooting
  12. plausible_events_db keeps restarting
  13. Bind for 127.0.0.1:8000 failed: port is already allocated
  14. The dashboard shows no visits
  15. Invitation or password reset emails never arrive
  16. Links in emails point to the wrong address
  17. Next steps

Plausible Analytics is a lightweight, privacy-focused web analytics tool with a single-page dashboard for visitors, pages, sources, locations, devices, goals and custom events. Plausible Community Edition (CE) is its self-hosted version: it runs as three containers, the Plausible app, PostgreSQL for accounts and settings, and ClickHouse for the event data. Plausible CE is open source.

This guide follows Plausible's official community-edition repository and wiki. You clone the current release, create the .env file with BASE_URL and SECRET_KEY_BASE, publish Plausible on 127.0.0.1:8000 with a Compose override file, and serve it over HTTPS with Caddy. You then create the first account, keep registration invite-only, connect an SMTP relay and learn how to back up, restore and upgrade both databases.

Prerequisites

Plausible's README lists two hardware requirements; the project does not publish a disk figure, so that value is a conservative starting point, not an official or benchmarked number:

ResourceMinimum (official)Suggested starting point
CPUx86-64 with SSE 4.2, or ARM with NEON (required by ClickHouse)2 vCPU
MemoryAt least 2 GB RAM recommended2 GB RAM, 4 GB for busier sites
DiskNot published20 GB; ClickHouse data grows with every tracked event

Step 1 — Check the CPU and install git

ClickHouse does not start on a CPU without SSE 4.2 (x86-64) or NEON (ARM). Check the flags your server reports:

Bash
grep -m1 -o -w sse4_2 /proc/cpuinfo || echo "sse4_2 not reported"
uname -m
sudo apt update
sudo apt install git

On an x86_64 server the first command should print sse4_2. On an aarch64 server, check for asimd instead with grep -m1 -o -w asimd /proc/cpuinfo; this is how Linux reports NEON.

Step 2 — Clone the current release

The community-edition repository has one branch per release. At the time of writing the current release is v3.2.1; check the Plausible releases for a newer one and use its name in the commands below:

Bash
sudo mkdir -p /opt/plausible-ce && sudo chown $USER:$USER /opt/plausible-ce
git clone -b v3.2.1 --single-branch https://github.com/plausible/community-edition /opt/plausible-ce
cd /opt/plausible-ce
ls

You should see compose.yml, a clickhouse folder with ClickHouse configuration files, and the README. compose.yml pins the matching image, here ghcr.io/plausible/community-edition:v3.2.1, together with postgres:16-alpine and a ClickHouse server image. Do not edit compose.yml; put your changes in .env and compose.override.yml, so that later upgrades with git pull stay clean.

Step 3 — Create the .env file

Create .env, restrict it to your user, and add the two required values. BASE_URL is the public address of your instance, and SECRET_KEY_BASE is a secret of at least 64 bytes, generated with the command from Plausible's documentation:

Bash
cd /opt/plausible-ce
touch .env
chmod 600 .env
echo "BASE_URL=https://plausible.example.com" >> .env
echo "SECRET_KEY_BASE=$(openssl rand -base64 48)" >> .env
echo "HTTP_PORT=8000" >> .env
echo "DISABLE_REGISTRATION=invite_only" >> .env
cat .env

HTTP_PORT=8000 makes Plausible listen on plain HTTP inside the container, as the reverse proxy page of the wiki describes, and leaving out HTTPS_PORT keeps its built-in TLS off. DISABLE_REGISTRATION=invite_only is already the default; writing it down makes the choice visible.

Step 4 — Publish Plausible on the loopback address

Create compose.override.yml next to compose.yml:

Bash
nano /opt/plausible-ce/compose.override.yml

Map the container port to 127.0.0.1:8000, exactly as in Plausible's reverse proxy guide:

YAML
services:
  plausible:
    ports:
      - 127.0.0.1:8000:${HTTP_PORT}

Start the stack. The first start pulls the images, creates the PostgreSQL database and runs the migrations before the app starts:

Bash
cd /opt/plausible-ce
docker compose up -d
docker compose ps
docker compose logs plausible --tail 30
curl --head http://127.0.0.1:8000

docker compose ps should list plausible, plausible_db and plausible_events_db, and the two databases should be healthy. The curl command should return HTTP/1.1 200 OK.

Step 5 — Serve Plausible over HTTPS with Caddy

Add a site block for the domain from BASE_URL to /etc/caddy/Caddyfile:

Caddyfile
plausible.example.com {
    reverse_proxy 127.0.0.1:8000
}

Reload Caddy, open the firewall for web traffic only, and test the public address:

Bash
sudo systemctl reload caddy
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
curl -I https://plausible.example.com

The domain in Caddy must match BASE_URL exactly, because Plausible uses BASE_URL to build links and to check the origin of dashboard connections. Caddy forwards the visitor's address in the X-Forwarded-For header, which Plausible uses to count unique visitors. The wiki also has Nginx and Apache examples; see Nginx with Certbot if you prefer Nginx.

Step 6 — Create your account and add a site

Open https://plausible.example.com straight away and register the first user: until that account exists, anyone who reaches the address could create it. Use a long, unique password, and turn on two-factor authentication in your account settings.

Then add your first website with its domain and copy the tracking snippet that Plausible shows. Paste it into the head section of every page of that site. Plausible 3.1 introduced a new tracker script and snippet; scripts installed with older versions keep working. Open your site in a browser and check the dashboard: the visit should appear in the realtime view within a minute.

With DISABLE_REGISTRATION=invite_only, other people can only join through an invitation that you send from Plausible. If you never want new accounts, set DISABLE_REGISTRATION=true in .env and run docker compose up -d.

Step 7 — Configure email

Plausible sends invitations, password resets, email verification and scheduled reports. Without SMTP_HOST_ADDR it tries to deliver mail directly to the recipients' mail servers, so configure an SMTP relay from a transactional email provider instead.

Add the relay settings to .env and recreate the container:

Bash
cd /opt/plausible-ce
echo "[email protected]" >> .env
echo "MAILER_NAME=Plausible" >> .env
echo "SMTP_HOST_ADDR=smtp.example.com" >> .env
echo "SMTP_HOST_PORT=587" >> .env
echo "SMTP_USER_NAME=your-smtp-username" >> .env
echo "SMTP_USER_PWD=change-me" >> .env
docker compose up -d

MAILER_EMAIL is the sender address and must belong to a domain your provider lets you send from. Port 587 is also Plausible's default for SMTP_HOST_PORT; leave SMTP_HOST_SSL_ENABLED at its default false for this port. Plausible also has API adapters for Postmark, Mailgun, Mandrill and SendGrid, selected with MAILER_ADAPTER and the matching API key variable. Test delivery by inviting a colleague or requesting a password reset, and check docker compose logs plausible --tail 50 if nothing arrives.

Back up and restore

Plausible CE keeps its state in two databases: PostgreSQL (plausible_db) holds users, sites, goals and settings, and ClickHouse (plausible_events_db) holds every pageview and event. Back up both, plus your .env and compose.override.yml. The PostgreSQL dump can run while Plausible is up. The ClickHouse data is copied as a volume archive with the containers stopped, Docker's documented way to back up a volume, so tracking requests that arrive during those minutes are lost; run it at a quiet time.

Compose prefixes volume names with the project folder name, so they are called plausible-ce_db-data, plausible-ce_event-data and so on. Confirm with docker volume ls, then run:

Bash
sudo mkdir -p /opt/backups && sudo chown $USER:$USER /opt/backups && chmod 700 /opt/backups
cd /opt/plausible-ce
docker compose exec -T plausible_db pg_dump -U postgres -Fc plausible_db > /opt/backups/plausible-db-$(date +%F).dump
docker compose stop plausible plausible_events_db
docker run --rm -v plausible-ce_event-data:/data -v /opt/backups:/backup alpine tar czf /backup/plausible-events-$(date +%F).tar.gz -C /data .
docker compose up -d
tar czf /opt/backups/plausible-config-$(date +%F).tar.gz -C /opt/plausible-ce .env compose.override.yml
ls -lh /opt/backups

Copy the three files off the server. To restore, clone the same release as in Step 2, put .env and compose.override.yml back in /opt/plausible-ce, and load both databases. Restore ClickHouse data only into the ClickHouse version it came from, which is the one pinned by the same release branch.

Bash
cd /opt/plausible-ce
docker compose down
docker volume rm plausible-ce_db-data plausible-ce_event-data
docker compose create
docker run --rm -v plausible-ce_event-data:/data -v /opt/backups:/backup alpine tar xzf /backup/plausible-events-2026-10-09.tar.gz -C /data
docker compose up -d --wait plausible_db
docker compose exec -T plausible_db createdb -U postgres plausible_db
docker compose exec -T plausible_db pg_restore -U postgres -d plausible_db < /opt/backups/plausible-db-2026-10-09.dump
docker compose up -d

Replace the dates with those of your backup files. docker compose create recreates the empty volumes and containers without starting them, so ClickHouse finds the restored files on its first start. Sign in and check that your sites and their history are back.

Update Plausible CE

Read the release notes for every version between yours and the new one, and back up first. Plausible's wiki points out that security patches and bug fixes are not backported to older releases, so stay current; v3.2.1, for example, fixed a remote code execution issue that affected v3.0.0-rc.0 to v3.2.0. The wiki's upgrade procedure pulls the new release branch into your clone and recreates the containers:

Bash
cd /opt/plausible-ce
git pull origin v3.2.1
docker compose up -d
docker compose ps
docker image prune

Replace v3.2.1 with the release branch named in the release notes. Because your settings live in the untracked files .env and compose.override.yml, git pull only updates compose.yml and the ClickHouse configuration; some releases, such as v3.2.0, change exactly those ClickHouse settings, which is why the notes ask you to switch branches instead of only changing the image tag. Migrations run automatically when the app container starts. Major PostgreSQL upgrades need a dump and restore; follow the wiki's Upgrade PostgreSQL page when a release asks for one.

Troubleshooting

plausible_events_db keeps restarting

ClickHouse cannot start. Read docker compose logs plausible_events_db --tail 50. On x86-64, missing SSE 4.2 support is a hard stop; check Step 1. If the logs mention memory, give the server more RAM; the repository's clickhouse folder already applies low-resource settings.

Bind for 127.0.0.1:8000 failed: port is already allocated

Another service on the host uses port 8000. Pick a free port, change HTTP_PORT in .env and the left-hand side of the mapping in compose.override.yml (for example 127.0.0.1:8100:${HTTP_PORT}), update the Caddy site block to match, and run docker compose up -d.

The dashboard shows no visits

Check that the snippet is on the page and that the domain you added in Plausible matches your site's hostname. Open the browser's developer tools on your site and look for a blocked request to your Plausible domain; ad blockers often block analytics scripts. Also confirm that BASE_URL matches the address in the snippet.

Invitation or password reset emails never arrive

Run docker compose logs plausible --tail 100 and look for SMTP errors. Typical causes are a wrong host or port, SMTP_HOST_SSL_ENABLED=true together with port 587, a MAILER_EMAIL address your provider does not allow, or a missing docker compose up -d after editing .env.

BASE_URL does not match the address users open. Set it to the exact HTTPS address, including the subdomain, run docker compose up -d, and make sure the Caddy site block uses the same domain.

Next steps

Frequently asked questions

Where does Plausible CE store its data?

In two databases: PostgreSQL holds users, sites, goals and settings, and ClickHouse holds every pageview and event. Both run as containers defined in compose.yml, so back up both, together with .env and compose.override.yml.

Why does Plausible CE need a CPU with SSE 4.2 or NEON?

Plausible stores events in ClickHouse, and ClickHouse requires the SSE 4.2 instruction set on x86-64 or NEON on ARM. Check the CPU flags of your server before you install.

Can Plausible CE handle HTTPS without a reverse proxy?

Yes. Since version 2.1.2 it can obtain Let's Encrypt certificates itself when HTTP_PORT is 80 and HTTPS_PORT is 443. This guide uses Caddy instead so the same server can host other web apps on ports 80 and 443.

Can anyone sign up on my Plausible instance?

Not by default. DISABLE_REGISTRATION defaults to invite_only, so after you create the first account new users can only join through an invitation. Set it to true to close registration completely.

Which HyperDC servers can run Plausible CE?

Plausible CE runs in Docker on any HyperDC Linux VPS, VDS or dedicated server with root access, a supported Ubuntu or Debian release and a CPU that reports SSE 4.2 or NEON.

Sources

Generera Lösenord

Please confirm