Analytics AWS

Plausible Analytics on AWS User Guide

| Product: Plausible Analytics on AWS

Overview

This image runs Plausible Community Edition 3.0.1, the open source, privacy friendly web analytics platform and a lightweight alternative to Google Analytics, on Ubuntu 24.04 LTS.

Plausible is a three tier application, and this image ships the complete stack as a pinned Docker Compose project in /opt/plausible:

Container Image Role
plausible ghcr.io/plausible/community-edition:v3.0.1 The Plausible application (Elixir / Phoenix)
plausible_db postgres:16-alpine Dashboard, site and user metadata
plausible_events_db clickhouse/clickhouse-server:24.12-alpine The analytics events store

The application listens on the loopback address 127.0.0.1:8000 by design and is never exposed directly. nginx is installed as a reverse proxy on port 80 that forwards every request to Plausible, with the WebSocket upgrade headers the live dashboard needs. PostgreSQL and ClickHouse stay inside the private Docker network and are never published to a host interface or to the network.

Plausible needs a SECRET_KEY_BASE, a TOTP vault key, a database password and an initial administrator. This image ships none of them baked in. On the first boot of every deployed instance a one shot service generates fresh per-instance values for all of them, resolves the instance's own public address through EC2 instance metadata (IMDSv2) to set BASE_URL, seeds a single administrator account with a freshly generated password, and writes the details to /root/plausible-credentials.txt (mode 0600, readable only by root). Open registration is disabled, so there is no public signup form on your analytics instance. Two instances launched from the same AMI never share a secret or a password.

All stack state - the PostgreSQL metadata, the ClickHouse events store and the application data - lives in Docker named volumes on a dedicated, independently resizable EBS data volume mounted at /var/lib/docker, kept separate from the operating system disk. The pinned image layers live there too, so first boot starts the stack in seconds rather than pulling gigabytes.

Plausible does not use cookies and does not collect personal data or persistent identifiers, so it needs no cookie banner and no consent prompt under GDPR, CCPA or PECR. The tracking script is roughly 1 KB.

The default security group for this listing opens port 22 (SSH) and port 80 (HTTP) only.

Prerequisites

  • An AWS account subscribed to this product in AWS Marketplace.
  • An EC2 key pair in your target region for SSH access.
  • A security group allowing inbound TCP 22 (SSH) from your IP and TCP 80 (HTTP) from your users.
  • Recommended instance type: m5.large or larger. ClickHouse is memory hungry; the image provisions a 4 GB swapfile on first boot and ships ClickHouse low resource configuration, but give it more memory for heavier traffic.
  • A website whose traffic you want to track.

Connecting to your instance

SSH in as the default login user for your operating system variant, using the key pair you launched with.

OS variant Login user Example
Ubuntu 24.04 ubuntu ssh -i your-key.pem ubuntu@<instance-public-ip>

Step 1 - Launch from AWS Marketplace

  1. Open the product page in AWS Marketplace and choose Continue to Subscribe, then Continue to Configuration.
  2. Select the Plausible Analytics 3.0.1 on Ubuntu 24.04 delivery option and your region, then Continue to Launch.
  3. Choose your instance type, VPC/subnet, key pair and the security group described above, and launch.

Step 2 - Launch from the AWS CLI

Replace the AMI ID with the one shown on the product's launch page for your region, and use your own key pair and security group.

aws ec2 run-instances \
  --image-id ami-xxxxxxxxxxxxxxxxx \
  --instance-type m5.large \
  --key-name your-key \
  --security-group-ids sg-xxxxxxxx \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=plausible}]'

Step 3 - Connect to your instance

ssh -i your-key.pem ubuntu@<instance-public-ip>

First boot brings the three containers up, runs the database migrations and seeds your administrator account. That takes a couple of minutes on a fresh instance. Confirm it has finished - the sentinel file appears only when first boot has completed successfully:

test -f /var/lib/cloudimg/plausible-firstboot.done && echo "first boot complete"

Step 4 - Retrieve your administrator password

On the first boot, a one shot service generated a unique administrator password for this instance. Read the credentials file (root only):

sudo cat /root/plausible-credentials.txt

You will see the sign-in URL, the administrator email admin@cloudimg.local, and the generated password. Keep this password somewhere safe - it is the only account on a fresh instance and registration is disabled.

Step 5 - Sign in to Plausible

Open http://<instance-public-ip>/ in your browser. You are taken to the Plausible sign-in page. Enter admin@cloudimg.local and the password from the credentials file, and sign in.

Plausible sign-in

You can verify from the instance that the sign-in round trip works, without printing the password anywhere. The helper reads the credential itself, proves the generated password is accepted and that a wrong password is rejected, and prints only the verdict:

sudo /usr/local/sbin/plausible-roundtrip.sh

Change the administrator password once you are signed in: open the user menu (top right) and choose Settings. You can invite additional users from the same menu - registration stays closed to the public.

Step 6 - Add your website and install the tracking script

On a fresh instance there are no sites yet.

  1. Choose + Add Website.
  2. Enter the Domain - just the naked domain or subdomain, without www or https (for example example.com) - pick your Reporting Timezone, and choose Install Plausible.
  3. Plausible shows the tracking snippet for that site.

Plausible tracking script

Copy the snippet and paste it into the <head> of every page of your website. It looks like this - the data-domain is the site you just added and the src host is your Plausible instance:

<script defer data-domain="example.com" src="http://<instance-public-ip>/js/script.js"></script>

On the same screen you can enable optional measurements before you copy the snippet - outbound links, file downloads, 404 pages, hashed page paths, custom events, custom properties and ecommerce revenue - which swap in a richer variant of the script.

Once the script is live and visitors arrive, pageviews appear on the dashboard in real time. The script is cookieless and collects no personal data, so no cookie banner is required.

Step 7 - Read your analytics

Selecting a site opens its dashboard: unique visitors, total visits, total pageviews, views per visit, bounce rate and visit duration across the top, with a visitor graph beneath and the reporting period selectable on the right.

Plausible dashboard

Below the graph, Top Sources breaks traffic down by referrer, channel or campaign, and Top Pages by page, entry page or exit page.

Plausible sources and pages

Further down, Locations maps visitors by country, region and city, and Devices breaks them down by browser, operating system and screen size.

Plausible locations and devices

Per-site configuration lives under Settings for <your site>, reached from the site menu: domain and reporting timezone, people and invitations, public visibility, goals, custom properties, imports and exports, traffic shields for IP addresses, countries, pages and hostnames, and email reports.

Plausible site settings

Setting your base URL and enabling HTTPS

This image serves HTTP on port 80 and sets BASE_URL to the instance public IP on first boot. For production, put your own domain in front and terminate TLS. Two common options:

  • AWS-managed TLS: put the instance behind an Application Load Balancer (or Amazon CloudFront) with an AWS Certificate Manager certificate, and forward to the instance on port 80.
  • On-instance TLS with Let's Encrypt: point a DNS record at the instance, open port 443 in the security group, then install certbot and obtain a certificate:
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d analytics.example.com

Either way, tell Plausible its public address afterwards, otherwise links and the tracking snippet still reference the IP. Edit BASE_URL in the environment file and restart the stack:

sudo sed -i 's#^BASE_URL=.*#BASE_URL=https://analytics.example.com#' /opt/plausible/.env
sudo systemctl restart plausible

After enabling HTTPS, update the src in your tracking snippet to use https:// and your domain.

Service management

The stack is managed by a single systemd unit, plausible.service, which runs docker compose up -d against /opt/plausible/compose.yml on boot and docker compose down on stop. nginx and the Docker daemon are separate units. Confirm they are all active:

systemctl is-active docker plausible nginx

Check the three containers are running:

sudo docker compose -f /opt/plausible/compose.yml ps --format 'table {{.Service}}\t{{.State}}'

Confirm that only the intended ports are exposed - the application is bound to loopback and the databases are not on a host interface at all, so only 22 and 80 are reachable from the network:

ss -tln | grep -E ':(80|8000|5432|8123) ' || true

Restart Plausible after a configuration change with sudo systemctl restart plausible. Configuration lives in /opt/plausible/.env (the per-instance secrets and BASE_URL); the Compose project and the ClickHouse configuration drop-ins are in /opt/plausible.

Health check

Plausible exposes an unauthenticated health endpoint that reports the application together with both databases. A 200 means the app, PostgreSQL and ClickHouse are all healthy:

curl -s -o /dev/null -w 'plausible health HTTP %{http_code}\n' http://127.0.0.1:8000/api/health

nginx also serves a static health endpoint on port 80, which answers as soon as the proxy is up:

curl -s -o /dev/null -w 'nginx health HTTP %{http_code}\n' http://127.0.0.1/health

Storage layout

All analytics data and the pinned images live on the dedicated EBS data volume mounted at /var/lib/docker, which is where both the Docker data root and the containerd image store are configured to write:

findmnt -no SOURCE,TARGET,FSTYPE,SIZE /var/lib/docker
sudo docker volume ls --filter name=plausible --format '{{.Name}}'

Backup and maintenance

  • Metadata backup: the dashboard, site and user metadata is in PostgreSQL. Dump it from the container:

text sudo docker compose -f /opt/plausible/compose.yml exec -T plausible_db \ pg_dump -U postgres plausible_db | gzip > plausible-db-$(date +%F).sql.gz

  • Events backup: the analytics events are in ClickHouse and are the bulk of the data. The most practical durable backup is an EBS snapshot of the data volume, which captures PostgreSQL, ClickHouse and the application data consistently at the block level. Use Amazon Data Lifecycle Manager or AWS Backup to schedule it.
  • Resizing storage: the volume mounted at /var/lib/docker is an ordinary EBS volume. Grow it from the EC2 console, then extend the filesystem on the instance (sudo growpart where applicable, then sudo resize2fs).
  • OS updates: apply security updates with sudo apt-get update && sudo apt-get upgrade. Reboot if a new kernel is installed; the stack comes back automatically.
  • Upgrading Plausible: back up first, then change the pinned image tag in /opt/plausible/compose.yml, pull and recreate. Follow the upstream upgrade notes at https://github.com/plausible/community-edition/wiki, which call out any migration steps between versions.

Support

This image is backed by 24/7 cloudimg technical support by email and chat - deployment, adding and tracking sites, reading the dashboard, database backup and scaling, and TLS termination. Plausible Community Edition is open source software licensed under the AGPL-3.0 and is shipped unmodified; cloudimg provides the packaging and support and is not affiliated with or endorsed by Plausible Insights OU.