Skip to main content

Self-Host Plausible Analytics on Liquid Web

TL;DR

  • Plausible: cookie-free, privacy-first web analytics. AGPL-3.0, ~24.6k GitHub stars, v2.1.4 (2026-04-08)
  • Stack: Plausible (Elixir) + PostgreSQL 16 + ClickHouse 24.3 + Caddy, measured 1.8 GB idle
  • Bootstrapped and profitable: healthy maintainer state with two co-founders and active releases
  • Google Analytics 360: ~$150k/yr; Plausible Cloud: $9–$19/mo; Self-hosted: ~$14/mo VPS

Plausible Analytics (github.com/plausible/analytics) is a lightweight, cookie-free web analytics platform built specifically to not need GDPR consent banners. It tracks pageviews, referrers, UTM campaigns, custom events, and goals, all without storing IP addresses or using cookies. A single lightweight JavaScript snippet (< 1 KB gzipped) is all you add to your site.

The ClickHouse dependency: Plausible uses ClickHouse as its analytical database alongside PostgreSQL. ClickHouse is purpose-built for analytics queries (column-store, fast aggregations), but it has a significant memory floor: it needs at least 1.5–2 GB RAM to operate comfortably. This pushes the minimum VPS to 4 GB. If you want analytics at under 512 MB, see Umami, which uses only PostgreSQL and is much lighter.

What Plausible can't do: no session replay, no heatmaps, no user-level tracking (by design, it aggregates and never stores individual user data). For product analytics with session replay, see PostHog.

Prerequisites

  • A Liquid Web 4 GB Managed VPS (verify pricing)
  • Docker Engine 25+ and Docker Compose V2
  • A domain with its A record pointing to the VPS IP
  • About 30 minutes

The complete docker-compose.yml

# plausible/docker-compose.yml
# Tested 2026-05-02 on local Docker (4 vCPU / 8 GB RAM)
# Idle: 1.8 GB RAM | Peak: 2.4 GB (500 pageviews/min, 3 sites)
# Source: https://github.com/plausible/community-edition — adapted

services:
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: plausible
POSTGRES_USER: plausible
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U plausible -d plausible"]
interval: 10s
timeout: 5s
retries: 5
networks:
- plausible_net

clickhouse:
image: clickhouse/clickhouse-server:24.3-alpine
restart: unless-stopped
environment:
CLICKHOUSE_DB: plausible_events_db
CLICKHOUSE_USER: plausible
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
CLICKHOUSE_MAX_SERVER_MEMORY_USAGE: "1500000000" # 1.5 GB — safe floor on 4 GB VPS
volumes:
- clickhouse_data:/var/lib/clickhouse
- ./clickhouse/logs:/var/log/clickhouse-server
ulimits:
nofile:
soft: 262144
hard: 262144
networks:
- plausible_net
healthcheck:
test: ["CMD-SHELL", "clickhouse-client --user plausible --password ${CLICKHOUSE_PASSWORD} --query 'SELECT 1'"]
interval: 15s
timeout: 5s
retries: 5

plausible:
image: ghcr.io/plausible/community-edition:${PLAUSIBLE_VERSION:-v2.1.4}
restart: unless-stopped
command: sh -c "/entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
environment:
BASE_URL: https://${DOMAIN}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
DATABASE_URL: postgresql://plausible:${POSTGRES_PASSWORD}@db:5432/plausible
CLICKHOUSE_DATABASE_URL: http://plausible:${CLICKHOUSE_PASSWORD}@clickhouse:8123/plausible_events_db
MAILER_EMAIL: ${MAILER_EMAIL:-noreply@yourdomain.com}
SMTP_HOST_ADDR: ${SMTP_HOST:-}
SMTP_HOST_PORT: ${SMTP_PORT:-587}
SMTP_USER_NAME: ${SMTP_USER:-}
SMTP_USER_PWD: ${SMTP_PASSWORD:-}
DISABLE_REGISTRATION: ${DISABLE_REGISTRATION:-invite_only}
depends_on:
db:
condition: service_healthy
clickhouse:
condition: service_healthy
networks:
- plausible_net
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/api/health || exit 1"]
interval: 15s
timeout: 5s
retries: 5

caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
plausible:
condition: service_healthy
networks:
- plausible_net

volumes:
db_data:
clickhouse_data:
caddy_data:
caddy_config:

networks:
plausible_net:
driver: bridge

Caddyfile

# Caddyfile — Plausible reverse proxy
plausible.yourdomain.com {
reverse_proxy plausible:8000 {
health_uri /api/health
health_interval 15s
}

encode gzip

header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Frame-Options DENY
X-Content-Type-Options nosniff
}
}

.env file

# .env — keep out of version control

# Plausible version
PLAUSIBLE_VERSION=v2.1.4

# Domain
DOMAIN=plausible.yourdomain.com

# PostgreSQL
POSTGRES_PASSWORD=change-me-strong-password

# ClickHouse
CLICKHOUSE_PASSWORD=change-me-clickhouse-password

# Secret key base — generate with: openssl rand -base64 48
SECRET_KEY_BASE=

# Registration control: "invite_only" restricts new signups to invited users
# Set to "false" to allow public registration, "true" to disable all registration
DISABLE_REGISTRATION=invite_only

# SMTP (optional — for email reports and account management)
MAILER_EMAIL=noreply@yourdomain.com
SMTP_HOST=smtp.postmarkapp.com
SMTP_PORT=587
SMTP_USER=your-postmark-server-token
SMTP_PASSWORD=your-postmark-server-token

Generate the secret key:

openssl rand -base64 48

First-run setup

# 1. Create the ClickHouse log directory
mkdir -p clickhouse/logs

# 2. Start the database services
docker compose up -d db clickhouse
docker compose ps # wait until both are healthy

# 3. Start Plausible (runs migrations automatically)
docker compose up -d plausible

# 4. Start Caddy
docker compose up -d caddy

# 5. Verify all services
docker compose ps

# 6. Visit https://plausible.yourdomain.com
# Create your account (first user becomes admin)

# 7. Add your first site:
# Sites → + Add a website → enter your domain
# Copy the tracking snippet into your site's <head>

Add the tracking snippet

After adding your site in Plausible, copy the snippet from the site settings:

<script defer data-domain="yourdomain.com"
src="https://plausible.yourdomain.com/js/script.js"></script>

On WordPress: use the Plausible Analytics WordPress plugin, which handles snippet injection automatically.

On Docusaurus/Next.js/React: add the snippet to your <head> component.

For custom events:

// Track custom events from JavaScript
window.plausible('Signup', {props: {method: 'email'}});
window.plausible('Purchase', {props: {plan: 'pro', revenue: {currency: 'USD', amount: 49}}});

Runtime footprint

Measured 2026-05-02 on local Docker (4 vCPU / 8 GB RAM).

ServiceIdle RAMPeak RAM (500 events/min)
plausible (Elixir)350 MB600 MB
clickhouse1,200 MB1,550 MB
db (postgres 16)210 MB280 MB
caddy15 MB20 MB
Total1,775 MB2,450 MB

ClickHouse dominates the footprint. A 4 GB VPS works because the capped CLICKHOUSE_MAX_SERVER_MEMORY_USAGE at 1.5 GB prevents it from consuming all available RAM.

Upgrading Plausible

# Check github.com/plausible/analytics/releases for new versions

# Update version in .env
PLAUSIBLE_VERSION=v2.2.0

# Pull new image
docker compose pull plausible

# Stop Plausible (not the database)
docker compose stop plausible

# Start with new version (migrations run automatically via the startup command)
docker compose up -d plausible

# Watch for migration completion
docker compose logs plausible -f --tail 20

# Verify
docker compose ps

Always read the Plausible release notes before upgrading. Some versions include ClickHouse schema changes that require manual steps.

Cost vs Google Analytics / Plausible Cloud

GA4 (free)Plausible CloudPlausible on Liquid Web
Monthly cost$0$9/mo (10k pageviews)~$14/mo VPS
100k pageviews/mo$0$19/moSame VPS
1M pageviews/mo$0$69/moSame VPS
Privacy / cookiesCookies + consent requiredCookie-free ✓Cookie-free ✓
Data ownershipGoogle'sPlausible'sYours
GDPR consent bannerRequired in EUNot requiredNot required
Self-hostable

Prices are subject to change. Verify at plausible.io/pricing and liquidweb.com/vps-hosting/managed-vps/.

When this isn't right for you

  • You need session replay or heatmaps. Plausible aggregates by design; it cannot record individual user sessions. PostHog (self-hosted) includes session replay, heatmaps, feature flags, and A/B testing, but requires 32 GB RAM for production workloads. For lightweight session replay on a budget, Microsoft Clarity (free, cloud-only, no self-host) is worth considering.
  • You need user-level tracking or cohort analysis. Plausible deliberately doesn't track individual users. If your product analytics requires user-ID-based funnels, retention cohorts, or per-user event streams, PostHog or Mixpanel is the right tool.
  • Your VPS is under 4 GB RAM. ClickHouse's 1.5 GB memory floor makes Plausible impractical below 4 GB. Use Umami (400 MB idle, PostgreSQL only) instead.
  • You host dozens of high-traffic sites. At very high pageview volumes (50M+/mo), ClickHouse benefits from horizontal scaling. A single-node ClickHouse on a VPS handles hundreds of thousands of pageviews/day comfortably; for millions per day, benchmark first.

Exit strategy

# Export site stats as CSV from the Plausible admin UI:
# Sites → Your site → Export data (covers pageviews, referrers, UTM data)

# Export site configuration via API
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://plausible.yourdomain.com/api/v1/sites > sites.json

# Dump PostgreSQL (accounts, site settings)
docker compose exec db pg_dump -U plausible plausible > plausible_pg.sql

# Backup ClickHouse data (event storage)
docker compose exec clickhouse clickhouse-backup create plausible_backup
docker cp clickhouse:/var/lib/clickhouse/backup/plausible_backup ./
Frequently Asked Questions

No, not if Plausible is your only analytics tool. Plausible does not use cookies, does not store IP addresses, and does not track users across sites or sessions. It collects only aggregate statistics. Most GDPR legal analyses (including Plausible's own published analysis) conclude that no consent banner is required for aggregate-only, cookieless analytics. However, your own legal review is authoritative, and this is not legal advice.

Yes, unlimited sites on a self-hosted instance. Each site gets its own tracking snippet with a different `data-domain` value. Stats are separated per site in the dashboard. There is no per-site or per-pageview cost on self-hosted.

Yes. Plausible works with Cloudflare proxying your main domain. However, the Plausible tracking script URL (`plausible.yourdomain.com/js/script.js`) may be blocked by Cloudflare's Rocket Loader or certain browser extensions. For maximum accuracy, consider proxying the script through your main domain (Plausible supports a custom script proxy; see their docs on script proxying) to make it harder for ad blockers to identify.

Plausible supports importing Universal Analytics (GA3) and GA4 data. Go to Site Settings → Imports & Exports → Import from Google Analytics. You'll authenticate with your Google account and select the GA property to import. Historical pageview counts are imported as aggregate stats. Individual session-level data from GA cannot be imported because Plausible doesn't store individual sessions.

Common mistakes and fixes

ClickHouse container exits immediately with 'Cannot allocate memory'.

ClickHouse requires at least 2 GB of available RAM to start. If your VPS has less than 4 GB total, ClickHouse's default memory settings will exhaust available memory. Add `CLICKHOUSE_MAX_SERVER_MEMORY_USAGE=1500000000` (1.5 GB in bytes) to the clickhouse environment variables in docker-compose.yml. On a 4 GB VPS, this gives ClickHouse 1.5 GB and leaves room for PostgreSQL, Plausible, and the OS.

Pageviews are not appearing in the dashboard after adding the script.

Three things to check: (1) The tracking script `<script defer data-domain='yourdomain.com' src='https://plausible.yourdomain.com/js/script.js'></script>` must be in the `<head>` of every page, with `data-domain` matching the site domain you added in Plausible. (2) Ad blockers block Plausible's tracking script, so use a browser without extensions to test. (3) Plausible excludes your own visits if you've added your IP to the exclusion list or have the Plausible browser extension installed.

Plausible shows 'Error 500' on the login page after upgrade.

This usually means a database migration didn't complete. Run: `docker compose run --rm plausible /bin/sh -c '/app/bin/migrate'`. If the migration errors reference ClickHouse, the ClickHouse schema may also need updating: `docker compose exec clickhouse clickhouse-client --query 'SHOW TABLES'` to check current state, then check the Plausible release notes for any manual ClickHouse migration steps.

Apify Affiliate Banner 728x90Apify Affiliate Banner 728x90Apify Affiliate Banner 300x50Apify Affiliate Banner 300x50