Plausible Community Edition (CE) can be self-hosted on Ubuntu 24.04 with Docker Compose, PostgreSQL, ClickHouse, persistent Docker volumes, and built-in HTTPS. For the current official quickstart, you do not need to install Nginx, Caddy, or Certbot just to get a trusted public TLS endpoint: Plausible CE can listen on ports 80 and 443 and manage Let's Encrypt certificates itself.
This tutorial follows the current Plausible CE v3.2.1 deployment layout verified on September 4, 2026. It uses the repository's compose.yml, stores required settings in .env, adds public port mappings through compose.override.yml, keeps the upstream Compose file untouched for easier upgrades, and uses the dashboard-generated tracking snippet rather than the older hard-coded /js/script.js pattern. Plausible's official quickstart recommends at least 2 GB of RAM and a CPU with SSE 4.2 on x86 or NEON support on ARM because ClickHouse is part of the stack.
Raff Technologies is the VM platform used by the original tutorial. The original workflow was tested on Ubuntu 24.04 LTS on a Raff 1 vCPU / 2 GB RAM VM (Tier 2). This revision re-verifies the upstream Plausible CE workflow and documentation; it does not claim a new end-to-end benchmark or capacity test. When you self-host Plausible, you are responsible for upgrades, backups, availability, monitoring, and recovery.
Prerequisites:
- Ubuntu 24.04 with at least 2 GB RAM recommended by Plausible CE
- A CPU with SSE 4.2 support on x86 or NEON support on ARM
- Docker Engine with the Docker Compose plugin
- SSH access with sudo privileges
- A domain such as
analytics.example.compointing to the VM - Public TCP ports 80 and 443 available for HTTPS
Step 1 — Verify Ubuntu, Docker, CPU support, memory, DNS, and web ports
Confirm the operating system:
cat /etc/os-release
Check Docker and Compose:
docker --version docker compose version
If Docker is not installed, use How to Install Docker on Ubuntu 24.04 before continuing.
Check memory:
free -h
Check CPU flags on an x86 VM:
lscpu | grep -i '^Flags' | grep -o 'sse4_2' || true
On ARM64 systems, inspect the feature line instead:
lscpu | grep -i '^Flags\|^Features'
Plausible's current CE quickstart requires a CPU that supports SSE 4.2 or NEON because ClickHouse depends on those instruction sets.
Check DNS in both address families:
dig +short A analytics.example.com dig +short AAAA analytics.example.com
Check whether another service already owns ports 80 or 443:
sudo ss -lntp | grep -E ':(80|443)\b' || true
A stale AAAA record can cause confusing HTTPS behavior even when the IPv4 A record is correct, so remove or correct IPv6 DNS if this server is not serving the hostname over IPv6.
Verify: Ubuntu should report 24.04, Docker Compose should work, the VM should meet the Plausible CE memory/CPU requirements, DNS should resolve to this server, and ports 80/443 should be available for the deployment.
Step 2 — Install the small host utilities used by this tutorial
Install Git, OpenSSL, DNS tools, and curl:
sudo apt update sudo apt install -y git openssl dnsutils curl ca-certificates
Do not reinstall Docker from a second package source if it is already working. Mixing Ubuntu's Docker packages with Docker's official repository packages can make future upgrades harder to reason about.
Confirm Git and OpenSSL are available:
git --version openssl version
Verify: git --version and openssl version should both return installed versions without errors.
Step 3 — Clone a pinned Plausible Community Edition release
Create a dedicated installation path owned by your administrative user:
sudo install -d -o "$USER" -g "$USER" /opt/plausible-ce
Clone the current CE release used by this revision:
git clone -b v3.2.1 --single-branch \ https://github.com/plausible/community-edition \ /opt/plausible-ce
Enter the project:
cd /opt/plausible-ce
Inspect the files:
ls -la git describe --tags --exact-match
The current repository layout includes compose.yml; older tutorials that expect docker-compose.yml or plausible-conf.env are describing an older CE setup.
Pinning an exact release makes upgrades intentional rather than silently changing your application stack whenever a floating image tag moves.
Verify: /opt/plausible-ce/compose.yml should exist and git describe --tags --exact-match should report v3.2.1 for this revision.
Step 4 — Create a protected Plausible environment file
Move into the project directory:
cd /opt/plausible-ce
Set a restrictive file-creation mask and generate the secret without printing it to the terminal:
umask 077 SECRET_KEY_BASE="$(openssl rand -base64 48 | tr -d '\n')"
Create .env:
cat > .env <<EOF BASE_URL=https://analytics.example.com SECRET_KEY_BASE=${SECRET_KEY_BASE} HTTP_PORT=80 HTTPS_PORT=443 DISABLE_REGISTRATION=invite_only EOF unset SECRET_KEY_BASE chmod 600 .env
Replace analytics.example.com with your real hostname before starting the stack.
BASE_URL is required and is used for generated links and Plausible's origin-related security checks. SECRET_KEY_BASE is also required; the current Plausible CE documentation uses openssl rand -base64 48 to generate it. DISABLE_REGISTRATION=invite_only makes the current default registration policy explicit.
Do not commit .env to Git or paste its secret values into support tickets.
Verify:
stat -c '%a %n' .env grep -E '^(BASE_URL|HTTP_PORT|HTTPS_PORT|DISABLE_REGISTRATION)=' .env
The file mode should be 600, the public URL should be correct, and the command should not print SECRET_KEY_BASE.
Step 5 — Expose Plausible with its built-in automatic HTTPS
Keep the tracked compose.yml untouched and put local deployment changes in compose.override.yml:
cd /opt/plausible-ce cat > compose.override.yml <<'EOF' services: plausible: ports: - "80:80" - "443:443" EOF
Plausible's official quickstart uses this override together with HTTP_PORT=80 and HTTPS_PORT=443. That combination enables Plausible CE's built-in Let's Encrypt certificate handling.
Using an override file also keeps local changes separate from the repository's versioned compose.yml, reducing unnecessary merge conflicts during future upgrades.
Validate the merged Compose configuration:
docker compose config -q
List the services and persistent volume definitions:
docker compose config --services docker compose config --volumes
The current v3.2.1 stack includes PostgreSQL, ClickHouse, the Plausible app, and persistent volumes for database, event, log, and Plausible application state.
Verify: docker compose config -q should exit successfully and the merged configuration should expose only the Plausible service on public ports 80 and 443.
Step 6 — Allow only the intended public traffic
Inspect UFW before making changes:
sudo ufw status verbose
If UFW is already active, confirm your actual SSH path is allowed before adding web ports. For a standard SSH service:
sudo ufw allow OpenSSH sudo ufw allow 80/tcp sudo ufw allow 443/tcp
If UFW is inactive, do not enable it blindly on a remote server. First make sure your SSH rule matches the port and source you actually use. See Set Up UFW Firewall on Ubuntu 24.04 for the full workflow.
Also review any provider-side firewall protecting the VM. Public HTTPS requires inbound TCP 80 and 443 to reach this host.
Docker publishes container ports using its own packet-filtering rules. Docker's documentation warns that published container ports can behave differently from ordinary UFW-managed host services, so do not treat UFW alone as the only network control for Docker workloads.
Verify: Your working SSH path should remain allowed, ports 80/443 should be reachable for Plausible, and no database or ClickHouse port should be intentionally exposed to the public internet.
Step 7 — Start Plausible CE and inspect the service state
Start the complete stack:
cd /opt/plausible-ce docker compose up -d
Check state:
docker compose ps
Inspect recent application logs:
docker compose logs --tail=100 plausible
Inspect database logs if startup does not settle:
docker compose logs --tail=100 plausible_db docker compose logs --tail=100 plausible_events_db
The current Compose file waits for PostgreSQL and ClickHouse health checks before starting the Plausible application. First startup can take longer because databases are initialized and application migrations run.
Do not use hard-coded RAM or startup-time expectations as a health check. Image versions, disk state, host load, and existing data all affect startup behavior.
Verify: docker compose ps should show PostgreSQL and ClickHouse healthy and the Plausible application running without a repeating restart loop.
Step 8 — Verify automatic HTTPS and create the first account
Test HTTPS from the server:
curl -I https://analytics.example.com
Test the HTTP path:
curl -I http://analytics.example.com
For a valid public hostname, HTTP should redirect to HTTPS and the HTTPS endpoint should return an application response with a trusted certificate.
If certificate issuance is still in progress or fails, inspect the application log rather than repeatedly restarting the stack:
docker compose logs --tail=150 plausible
Open in a browser:
https://analytics.example.com
Create the first user account. With DISABLE_REGISTRATION=invite_only, future public self-registration is restricted. If you plan to invite other users or require email verification, configure a supported mail provider using Plausible's current CE configuration options before relying on email workflows.
Verify: The dashboard should load over trusted HTTPS, the first account should sign in successfully, and plain HTTP should redirect to the HTTPS hostname.
Step 9 — Add a website and use the dashboard-generated tracking snippet
In Plausible, add the domain you want to measure. For example, add example.com rather than including https:// in the site domain field.
Then open the site's installation or tracking settings and copy the exact tracking snippet generated by your Plausible instance into the <head> of your website.
Do not copy the old generic pattern from outdated tutorials:
/js/script.js
Plausible introduced a newer site-specific tracking script model in October 2025. The current snippet is generated for the site and can reflect enabled tracking options. Using the dashboard-generated snippet avoids hard-coding a path that may not match the current tracker configuration.
After adding the snippet, deploy the website change and load the site in a browser.
Official current tracking guidance: Add the Plausible tracking script.
Verify: View the website's rendered HTML or browser developer tools and confirm the exact Plausible snippet from the site's installation screen is present in the page <head>.
Step 10 — Verify analytics end to end from a real browser visit
Open the tracked website in a normal browser session and navigate between a few pages.
In browser developer tools, open Network and filter for your Plausible hostname. Confirm that the tracker script loads and that an analytics event request is sent when a pageview occurs.
Then return to the Plausible dashboard and use its installation check or realtime view to confirm the visit is being received.
This is a better production verification than posting a fabricated event with a forged X-Forwarded-For header or querying an internal ClickHouse table name. Internal schemas and tracker payloads can change between CE releases; the public tracker and dashboard are the interfaces your real site depends on.
If the request is blocked, check browser extensions, Content Security Policy, the generated snippet, the site's domain setting, and the Plausible BASE_URL before changing database configuration.