If you want full ownership of your website analytics without sending visitor data to a third party, Plausible Community Edition (CE) is one of the best options available today. It gives you a lightweight, privacy-focused analytics dashboard that runs entirely on your own server. This tutorial walks you through every step of a production-ready plausible community edition self-hosted deployment, from initial server setup to SSL, tracking, and ongoing maintenance.
This guide is part of our complete guide to self-hosted analytics, where we compare every major platform you can run on your own infrastructure.
Plausible CE vs Plausible Cloud
Plausible Analytics exists in two forms: the managed Plausible Cloud service and the free Plausible Community Edition you host yourself. Before you commit to self-hosting, understand the trade-offs.
| Feature | Plausible Cloud | Plausible CE |
|---|---|---|
| Core analytics dashboard | Yes | Yes |
| Goal and event tracking | Yes | Yes |
| Privacy and GDPR compliance | Yes | Yes |
| Google Search Console integration | Yes | Yes (manual setup) |
| Managed infrastructure | Yes | No (you manage it) |
| Automatic updates | Yes | No (manual pull) |
| Priority email support | Yes | Community only |
| Revenue tracking | Yes | Yes |
| Funnels | Yes | Yes |
| Cost (10k monthly pageviews) | $9/month | Free + server costs |
| Cost (1M monthly pageviews) | $69/month | Free + server costs |
When to self-host: You need full data sovereignty, you already manage servers, you want to avoid recurring SaaS fees, or your organization requires that analytics data never leaves your infrastructure. A small VPS costs $5-10/month, which covers most use cases.
When to pay for Cloud: You don’t want to deal with server maintenance, updates, backups, or troubleshooting ClickHouse memory issues. For small sites, the Cloud plan can be cheaper than maintaining a VPS when you factor in your time.
For a deeper comparison of privacy-focused analytics platforms, see our review of Matomo vs Plausible vs Fathom.
Prerequisites
Before starting the deployment, make sure you have the following ready:
- A VPS with at least 2 GB RAM — ClickHouse (the analytics database) needs memory. A 2 GB VPS handles up to roughly 100k monthly pageviews comfortably. For higher traffic, plan for 4 GB or more.
- Docker and Docker Compose — Plausible CE ships as a set of Docker containers. Install Docker Engine (not Docker Desktop) on your server.
- A domain or subdomain — For example,
analytics.yourdomain.com. Point an A record to your server IP before continuing. - SMTP credentials (optional but recommended) — Required for email reports, password resets, and spike notifications. Any SMTP service works: Mailgun, Amazon SES, Postmark, or your own mail server.
Install Docker and Docker Compose if they are not already present:
# Install Docker on Ubuntu/Debian
curl -fsSL https://get.docker.com | sh
sudo systemctl enable docker
sudo systemctl start docker
# Verify installation
docker --version
docker compose version
Step 1: Clone the Hosting Repository
Plausible provides an official hosting repository with the Docker Compose configuration and example environment files. Clone it to your server:
git clone https://github.com/plausible/community-edition.git plausible-ce
cd plausible-ce
The repository contains the following key files:
docker-compose.yml— Defines the three services: Plausible web app, PostgreSQL, and ClickHouse.plausible-conf.env— Environment variables for the Plausible container.clickhouse/clickhouse-config.xml— ClickHouse server configuration.clickhouse/clickhouse-user-config.xml— ClickHouse user-level settings.reverse-proxy/— Example configs for Nginx and Traefik (optional reference).
Step 2: Configure Environment Variables
Open plausible-conf.env and set the required values. This file controls how Plausible behaves.
First, generate a secret key. This is used for session signing and encryption:
openssl rand -base64 48
Now edit the environment file:
# plausible-conf.env
# The URL where Plausible will be accessible (no trailing slash)
BASE_URL=https://analytics.yourdomain.com
# Secret key for signing sessions — paste the output of openssl command above
SECRET_KEY_BASE=your-generated-secret-key-here
# Disable public registration after creating your admin account
DISABLE_REGISTRATION=invite_only
# TOTP (two-factor auth) vault key — generate another random string
TOTP_VAULT_KEY=another-random-base64-string
# SMTP configuration for email reports and password resets
[email protected]
SMTP_HOST_ADDR=smtp.mailgun.org
SMTP_HOST_PORT=587
[email protected]
SMTP_USER_PWD=your-smtp-password
SMTP_HOST_SSL_ENABLED=false
SMTP_RETRIES=2
Key points about these settings:
- BASE_URL must match the exact URL visitors will use. If you use a subdomain with HTTPS, include the full
https://prefix. - SECRET_KEY_BASE must be at least 64 characters. Never share it or commit it to version control.
- DISABLE_REGISTRATION should be set to
invite_onlyafter you create your first admin account. You can also set it totrueto block all new registrations entirely. - Without SMTP settings, Plausible still works for basic tracking, but you will not receive email reports or be able to reset passwords via email.
Step 3: Customize docker-compose.yml
The default docker-compose.yml works for most deployments. Here is a production-ready version with resource limits and proper volume configuration:
services:
plausible:
image: ghcr.io/plausible/community-edition:v2.1
restart: always
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
depends_on:
plausible_db:
condition: service_healthy
plausible_events_db:
condition: service_healthy
ports:
- "127.0.0.1:8000:8000"
env_file:
- plausible-conf.env
deploy:
resources:
limits:
memory: 1G
plausible_db:
image: postgres:16-alpine
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
plausible_events_db:
image: clickhouse/clickhouse-server:24.3-alpine
restart: always
volumes:
- event-data:/var/lib/clickhouse
- event-logs:/var/log/clickhouse-server
- ./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
deploy:
resources:
limits:
memory: 1G
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
driver: local
event-data:
driver: local
event-logs:
driver: local
A few things to note in this configuration:
- The
portsdirective binds to127.0.0.1:8000, meaning the app is only accessible locally. You will put a reverse proxy in front of it for public access. - Resource limits prevent ClickHouse or Plausible from consuming all server memory during traffic spikes.
- Named volumes (
db-data,event-data) persist data across container restarts and upgrades. - Health checks ensure services start in the correct order.
The ClickHouse config file clickhouse/clickhouse-config.xml controls logging and memory behavior. For a 2 GB VPS, use conservative settings:
<clickhouse>
<logger>
<level>warning</level>
<console>true</console>
</logger>
<max_server_memory_usage_to_ram_ratio>0.5</max_server_memory_usage_to_ram_ratio>
</clickhouse>
This limits ClickHouse to 50% of available RAM, leaving room for PostgreSQL, Plausible, and the operating system.
Step 4: Launch and Verify
Start the stack in detached mode:
docker compose up -d
Watch the logs to confirm everything starts correctly:
# Follow all service logs
docker compose logs -f
# Or check a specific service
docker compose logs -f plausible
Initial startup takes 30-60 seconds. You will see database migrations running, then a message like:
[info] Running PlausibleWeb.Endpoint with Bandit 1.x at :::8000 (http)
Verify the app is responding:
curl -s http://localhost:8000 | head -20
If you see HTML output, the application is running. Open your browser and navigate to http://your-server-ip:8000 (or use an SSH tunnel if port 8000 is firewalled). You will be greeted by the registration page. Create your admin account here, then immediately set DISABLE_REGISTRATION=invite_only in plausible-conf.env and restart:
docker compose restart plausible
Step 5: Reverse Proxy and SSL
A reverse proxy serves Plausible over HTTPS on port 443 and handles SSL termination. Here is a complete Nginx configuration:
# /etc/nginx/sites-available/analytics.yourdomain.com
server {
listen 80;
server_name analytics.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name analytics.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/analytics.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket support for live dashboard updates
location /api/live/websocket {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable the site and obtain an SSL certificate with Certbot:
# Install Certbot if not already installed
sudo apt install certbot python3-certbot-nginx -y
# Enable the Nginx config
sudo ln -s /etc/nginx/sites-available/analytics.yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
# Obtain SSL certificate
sudo certbot --nginx -d analytics.yourdomain.com
# Verify auto-renewal
sudo certbot renew --dry-run
The WebSocket location block is essential. Without it, the real-time visitor counter on the Plausible dashboard will not update live. The proxy_http_version 1.1 and Upgrade headers enable the persistent WebSocket connection.
Step 6: Add Sites and Start Tracking
Log in to your Plausible dashboard at https://analytics.yourdomain.com. Click Add a website and enter your domain (e.g., example.com).
Plausible gives you a tracking script to add to every page of your site. Place it in the <head> section:
<script defer data-domain="example.com"
src="https://analytics.yourdomain.com/js/script.js"></script>
If you want to track outbound link clicks, file downloads, or 404 pages, use the extended script variants:
<!-- Track outbound links and file downloads -->
<script defer data-domain="example.com"
src="https://analytics.yourdomain.com/js/script.outbound-links.file-downloads.js"></script>
After adding the script, visit your website in a browser and check the Plausible dashboard. You should see yourself as a real-time visitor within seconds.
Setting up goals: Goals let you track specific actions like button clicks, form submissions, or pageview-based conversions. In the Plausible dashboard, go to your site settings and click Goals. You can create two types:
- Pageview goals — Trigger when a visitor views a specific page, e.g.,
/thank-you. - Custom event goals — Trigger from JavaScript events you define. For example, to track a signup button click:
<button onclick="plausible('Signup')">Sign Up</button>
Then create a custom event goal named Signup in the dashboard. Plausible will start counting conversions immediately.
For a comprehensive look at how privacy-focused tools like Plausible handle GDPR, read our comparison of privacy and GDPR compliance features.
Email Reports and Alerts
Once SMTP is configured, Plausible offers two valuable email features: scheduled reports and traffic spike notifications.
Scheduled email reports: Go to your site settings, then Email Reports. You can enable weekly and monthly reports. Each report summarizes top pages, sources, countries, and overall traffic. You can add multiple recipients, including team members who do not have Plausible accounts.
Spike notifications: Under the same settings area, enable Traffic Spike Notifications. Set a threshold — for example, alert when current visitors exceed 50. Plausible checks every few minutes and sends an email when the threshold is crossed. This is useful for detecting viral content, successful launches, or unexpected traffic from a mention on a popular site.
Both features require working SMTP. If emails are not arriving, check your SMTP credentials in plausible-conf.env and verify with:
docker compose logs plausible | grep -i mail
Updating Plausible CE
Plausible CE releases updates regularly. The update process is straightforward but should always include a backup step.
Before updating, back up your databases:
# Backup PostgreSQL
docker compose exec plausible_db pg_dump -U postgres plausible > backup_postgres_$(date +%Y%m%d).sql
# Backup ClickHouse data (stop writes first for consistency)
docker compose stop plausible
docker run --rm -v plausible-ce_event-data:/data -v $(pwd):/backup alpine \
tar czf /backup/clickhouse_backup_$(date +%Y%m%d).tar.gz /data
docker compose start plausible
Pull the latest images and restart:
# Check the release notes first
# https://github.com/plausible/analytics/releases
# Pull updated images
docker compose pull
# Restart with the new images
docker compose up -d
# Monitor logs for migration issues
docker compose logs -f plausible
Plausible runs database migrations automatically on startup. If a migration fails, check the release notes for breaking changes. Major version bumps (e.g., v1.x to v2.x) may require manual steps — always read the changelog before upgrading.
A good update routine:
- Read the release notes for the new version.
- Back up PostgreSQL and ClickHouse data.
- Update the image tag in
docker-compose.ymlif you pin specific versions. - Run
docker compose pullanddocker compose up -d. - Check logs for errors and verify the dashboard loads correctly.
Troubleshooting Common Issues
Here are the most frequent problems people encounter with Plausible CE and how to fix them:
ClickHouse running out of memory
Symptoms: The container restarts repeatedly, or docker compose logs plausible_events_db shows OOM (out of memory) errors. Fix: Lower the ClickHouse memory ratio in the config XML, add swap space, or upgrade your VPS to 4 GB RAM.
# Add 2GB swap if you are on a 2GB VPS
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Database migration errors on startup
If Plausible fails to start after an update with migration errors, check that PostgreSQL is fully ready before Plausible attempts to connect. The health check in the Docker Compose file should handle this, but you can increase the sleep duration in the Plausible command:
command: sh -c "sleep 20 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
Tracking script blocked by ad blockers
Some browser extensions block requests to known analytics domains. Plausible offers a proxy workaround. Create a reverse proxy rule that serves the script from your own domain:
# Add to your main website's Nginx config
location = /js/visit.js {
proxy_pass https://analytics.yourdomain.com/js/script.js;
proxy_set_header Host analytics.yourdomain.com;
}
location = /api/event {
proxy_pass https://analytics.yourdomain.com/api/event;
proxy_set_header Host analytics.yourdomain.com;
proxy_buffering on;
}
Then update your tracking script to use the proxied path:
<script defer data-domain="example.com" data-api="/api/event"
src="/js/visit.js"></script>
No data showing in the dashboard
If you have added the script but see no data, work through this checklist:
- Check the browser console — Look for 404 errors on the script URL or blocked requests.
- Verify data-domain matches — The
data-domainattribute must exactly match what you configured in Plausible (no www vs www mismatch). - Confirm BASE_URL is correct — If BASE_URL in your env file does not match the actual URL, API calls will fail.
- Check browser extensions — Disable ad blockers and privacy extensions temporarily.
- Inspect network requests — The script should fire a POST to
/api/eventon each pageview. Check the Network tab in your browser dev tools.
Bottom Line
Deploying Plausible Community Edition gives you a fully functional, privacy-respecting analytics platform that you control completely. The stack — Plausible, PostgreSQL, and ClickHouse — runs comfortably on a modest VPS, and the Docker-based setup makes both deployment and updates predictable.
The initial setup takes about 30 minutes if you have Docker experience. After that, maintenance is minimal: pull new images when updates release, keep backups of your databases, and monitor disk and memory usage on your server. For most small to mid-size websites, this is a practical and cost-effective alternative to both Google Analytics and the paid Plausible Cloud service.
If you are evaluating other self-hosted options alongside Plausible, our self-hosted analytics complete guide covers every major platform with setup instructions and comparison tables.
