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
- Prerequisites
- Step 1 — Check the CPU and install git
- Step 2 — Clone the current release
- Step 3 — Create the .env file
- Step 4 — Publish Plausible on the loopback address
- Step 5 — Serve Plausible over HTTPS with Caddy
- Step 6 — Create your account and add a site
- Step 7 — Configure email
- Back up and restore
- Update Plausible CE
- Troubleshooting
- plausible_events_db keeps restarting
- Bind for 127.0.0.1:8000 failed: port is already allocated
- The dashboard shows no visits
- Invitation or password reset emails never arrive
- Links in emails point to the wrong address
- 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
- A server running Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12 or Debian 13.
- A non-root user with
sudorights. See Secure a new Linux server and Set up SSH keys. - Docker Engine with the Compose plugin: Install Docker on Ubuntu or Install Docker on Debian. You also need
git. - Caddy installed on the host as described in Caddy as a reverse proxy.
- A domain name such as
plausible.example.comwith an A record (and AAAA record if you use IPv6) pointing at your server.
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:
| Resource | Minimum (official) | Suggested starting point |
|---|---|---|
| CPU | x86-64 with SSE 4.2, or ARM with NEON (required by ClickHouse) | 2 vCPU |
| Memory | At least 2 GB RAM recommended | 2 GB RAM, 4 GB for busier sites |
| Disk | Not published | 20 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:
grep -m1 -o -w sse4_2 /proc/cpuinfo || echo "sse4_2 not reported"
uname -m
sudo apt update
sudo apt install gitOn 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:
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
lsYou 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:
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 .envHTTP_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:
nano /opt/plausible-ce/compose.override.ymlMap the container port to 127.0.0.1:8000, exactly as in Plausible's reverse proxy guide:
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:
cd /opt/plausible-ce
docker compose up -d
docker compose ps
docker compose logs plausible --tail 30
curl --head http://127.0.0.1:8000docker 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:
plausible.example.com {
reverse_proxy 127.0.0.1:8000
}Reload Caddy, open the firewall for web traffic only, and test the public address:
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.comThe 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:
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 -dMAILER_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:
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/backupsCopy 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.
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 -dReplace 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:
cd /opt/plausible-ce
git pull origin v3.2.1
docker compose up -d
docker compose ps
docker image pruneReplace 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.
Links in emails point to the wrong address
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
- Compare with another lightweight tool: How to install Umami.
- Need ecommerce reports and a classic PHP stack? See How to install Matomo.
- Learn more about override files in Docker Compose basics.
- See servers for self-hosted analytics on the web analytics hosting page.
- Read the Plausible CE wiki for every configuration option.
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.