Innovate | Connect | Transform
ContactService statusUSD $

GICT knowledge base

Deploy Plausible Analytics on Your VPS: An Open-Source Google Analytics Alternative

Published

Self Hosted
photo_6147878739858100371_y

Google Analytics is free, but you pay for it in ways that are not on the invoice. Your visitors get tracked across sites they have never heard of. You get GDPR compliance headaches and cookie consent banners that annoy half your users. And every page load pulls in several hundred kilobytes of tracking code that slows your site down.

Plausible Analytics solves all three problems. It runs on your own server, so your visitors’ data never leaves your control. It does not use cookies, which means no consent banners under GDPR, PECR, and CCPA. The tracking script is under 1 KB and loads asynchronously, so it does not slow your pages down.

It is not as feature-rich as Google Analytics. But for most websites, Google Analytics has way more than you actually need. Plausible gives you the numbers that matter: pageviews, unique visitors, bounce rate, referral sources, and top pages. Nothing else.

What you need before you start

Three things are non-negotiable before you begin:

A VPS with at least 2 GB of RAM. Plausible runs three separate containers: the main application, a PostgreSQL database for user and site data, and a ClickHouse database for your analytics events. ClickHouse is the component that needs memory. 2 GB is the bare minimum. If you plan to run multiple sites or expect decent traffic, 4 GB is more comfortable.

Ubuntu 22.04 or 24.04 on that server. The steps below are written for Ubuntu. They will work on Debian with minimal changes.

A domain name with an A record pointing to your server. You cannot use an IP address here. Caddy, which handles your HTTPS certificate automatically, needs the domain to match the certificate request. Something like analytics.yourdomain.com works perfectly.

Check your available RAM

free -h

Look at the “total” column under “Mem”. If it says under 2G, do not proceed. Plausible will run out of memory and the container will crash repeatedly.

Point your domain at your server

Go to your DNS provider and create an A record:

Type: A
Name: analytics
Value: YOUR_SERVER_IP
TTL: 300

The TTL of 300 means the record propagates in about 5 minutes. Higher values can take hours. If your DNS provider does not let you set TTL, just create the record and wait 10 minutes before moving on.

Verify it propagated:

dig +short analytics.yourdomain.com

Should print your server IP and nothing else. If it returns an empty answer, either wait longer or check the record again.

Install Docker

If Docker is already on your server, skip this step. Run docker –version to check.

If it is not installed:

curl -fsSL https://get.docker.com | sh
apt install -y docker-compose-plugin
systemctl enable docker

The official Docker install script detects your OS and sets up the daemon. The docker-compose-plugin gives you the docker compose command (v2 syntax). Verify:

docker --version
docker compose version

Both should return version numbers without errors.

Download Plausible

Clone the official community edition repository. Pinning to a specific version (v3.2.1 as of this writing) is safer than using the main branch, which might change between when this article was written and when you read it.

git clone -b v3.2.1 --single-branch https://github.com/plausible/community-edition plausible-ce
cd plausible-ce

Check what you downloaded:

ls -la

You should see docker-compose.yml, a clickhouse/ directory, and nothing else. The repo is intentionally minimal.

Configure the environment

Create a .env file with the two required variables:

touch .env
echo "BASE_URL=https://analytics.yourdomain.com" >> .env
echo "SECRET_KEY_BASE=$(openssl rand -base64 48)" >> .env

BASE_URL must be the exact domain where you plan to access Plausible, including https://. No trailing slash. Caddy uses this to request the correct TLS certificate from Let’s Encrypt. If you type analytics.yourdomain.com here, you must access Plausible at analytics.yourdomain.com, not at some other subdomain or path.

The secret key is generated randomly. Each time you run this command, you get a different 64-character string. This key encrypts session data and other sensitive values. Do not share it or lose it – if you lose it and need to restore from backup, you will need the same key.

Verify your .env looks right:

cat .env

You should see BASE_URL and SECRET_KEY_BASE lines. The secret key will be a long random string.

Expose ports for automatic HTTPS

Plausible CE ships with Caddy as its built-in web server and reverse proxy. Caddy handles HTTPS automatically – it requests certificates from Let’s Encrypt, serves them, and renews them before they expire. You do not need to run certbot separately or manage certificates manually.

Create a compose override file to expose ports 80 and 443:

cat > compose.override.yml << 'EOF'
services:
    plausible:
        ports:
            - 80:80
            - 443:443
EOF

This appends port mappings to whatever is already in docker-compose.yml. Port 80 is required for Caddy to answer the Let’s Encrypt HTTP-01 challenge. Port 443 serves the HTTPS traffic.

One important check: make sure nothing else is already listening on these ports.

ss -tlnp | grep -E ':80\s|:443\s'

If either port shows output, something is already using it. nginx, Apache, or another web server. Stop it before proceeding:

systemctl stop nginx
systemctl stop apache2
# OR find and stop whatever is using the port
systemctl stop servicename

Launch everything

Run the containers:

docker compose up -d

Docker pulls the three images (Plausible, PostgreSQL, ClickHouse), creates the containers, and starts them in the background. Give it about 20 seconds, then check status:

docker compose ps

All three services should show “Up” under the STATUS column. If any show “Restarting” or “Exit” with a non-zero code, check the logs:

docker compose logs plausible
docker compose logs plausible_events_db

ClickHouse restarting almost always means not enough RAM. PostgreSQL failing to start usually means the volume permissions are wrong on a first run. Both are solvable.

Once all three are Up, check if Plausible is responding:

curl -s http://localhost:8000/api/health

Should return a JSON response showing all services healthy. If you see connection refused, wait another 10 seconds and try again. The databases sometimes take longer to initialize on first run.

Create your account and first site

Open your browser and go to https://analytics.yourdomain.com. You should see the Plausible registration page. Fill in:

  • Your email address
  • A strong password
  • The name of your first site (yourdomain.com or a project name)

Click Create account. You are taken to the dashboard.

Click “Add a website” in the top right if your site was not created during registration. Enter your domain exactly as it appears in your browser bar – no https:// prefix, no trailing slash. Copy the tracking script Plausible shows you.

Add the tracking script to your site

Paste this into the <head> section of your website, just before the closing </head> tag:

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

Replace yourdomain.com with your actual domain. The defer attribute means the script does not block your page from loading. The data-domain attribute tells Plausible which site to attribute the traffic to.

Visit your site in a browser. Wait 30 seconds. Refresh your Plausible dashboard. You should see your first pageview recorded. If not, open the browser developer console (F12), go to the Network tab, and look for a request to /api/events – if it returns 200, the tracking is working.

Lock down registration

Right now anyone who visits your Plausible URL can create their own account and start tracking sites. You want only you using it. Add DISABLE_REGISTRATION to your .env file:

echo "DISABLE_REGISTRATION=true" >> .env
docker compose up -d plausible

The registration page closes after the first account exists. If no users have been created yet, the registration page stays open so you can create your first account. Once the first user exists, new registrations are blocked. The login page continues to work for existing users. You can invite additional users from the admin panel after logging in.

Upgrading to a new version

Plausible releases updates every few weeks. To upgrade:

git -C /path/to/plausible-ce fetch origin
git -C /path/to/plausible-ce checkout vX.X.X
docker compose pull
docker compose up -d

Replace vX.X.X with the latest version number from the GitHub releases page. The docker-compose.yml and .env file are preserved across version changes. On first startup after a major version upgrade, Plausible runs any pending database migrations automatically.

The short version

Clone the Plausible CE repo, set BASE_URL and SECRET_KEY_BASE in a .env file, expose ports 80 and 443 with a compose override, run docker compose up -d, and create your account. Caddy handles HTTPS automatically from there.

The whole process takes about 20 minutes on a clean VPS with good network connectivity. What you get is a self-hosted analytics platform that respects your visitors’ privacy, does not require cookie banners, and keeps all your data on your own server.

Need a VPS with enough RAM to run Plausible comfortably? InterServer VPS plans start at $5/month with scalable RAM options. 4 GB handles Plausible with room to spare.

Related guides

Account services are unavailable until the production backend is configured.