← Back to Blog

Umami or Plausible on a VPS: Cookie-Free Website Analytics Hosted in the EU

Published · by RS Computers

Analytics Privacy Docker

Umami or Plausible? If you want cookie-free website analytics on your own VPS with the least RAM, pick Umami: in our lab it ran in about 230 MB of memory as two Docker containers. Pick Plausible Community Edition if you prefer its one-page dashboard and can give it 2 GB of RAM, because it adds a ClickHouse database and used about 700 MB at idle. Both count visitors without cookies, and both keep every pageview on a server you choose. On a server in Amsterdam or Dublin, that data never leaves the EU and no analytics company sits in between.

Key facts, checked on 9 October 2026:

How analytics can count visitors without cookies

A cookie is a small file a website stores in your browser so it can recognise you on the next visit. Google Analytics and most ad tools rely on one. Umami and Plausible skip it. Instead, the server builds a short fingerprint for each visit and throws the raw ingredients away.

We checked both in the lab. Neither tracking script sent a Set-Cookie header. Umami's session table holds browser, OS, device, screen, language and location, but has no column for the IP address. Plausible's ClickHouse event table stores a numeric user_id (the daily hash) and no IP either.

Two EU laws meet here. The ePrivacy Directive, Article 5(3), says you need consent to store or read information on a visitor's device, unless it is strictly necessary for the service. The GDPR then covers any personal data you process, and an IP address is personal data even if you only hold it for a moment.

Many people assume "no cookies" means "no ePrivacy". The European Data Protection Board disagrees. In its 2024 guidelines, JavaScript that tells the browser to send information to a server counts as gaining access to the device, cookie or not. What saves privacy-first tools in many countries is the audience measurement exemption. The French regulator, the CNIL, lists the conditions:

A self-hosted tool fits that list well, because nobody else gets the data and nothing follows visitors across sites. The CNIL also notes that "most large audience measurement offerings" fall outside the exemption whatever their settings. Rules differ between member states, though, so check your own regulator's guidance. Whatever you decide about the banner, mention the analytics tool in your privacy policy.

Why the server's location still matters

Google says Google Analytics 4 "does not log or store individual IP addresses" from EU, Swiss or UK users, and that the IP lookup runs on servers in those regions before the data goes on to Analytics (Google Analytics Help). The rest of the data still ends up with a US company. In 2022, the CNIL sent formal notices to French websites over Google Analytics transfers to the United States (CNIL 2022 enforcement review).

Those transfers have been legal again since 10 July 2023, when the European Commission adopted the EU-US Data Privacy Framework (European Commission). The EU General Court upheld it on 3 September 2025 in case T-553/23, and an appeal to the Court of Justice (C-703/25 P) was still pending in October 2026. That court struck down the two earlier frameworks, Safe Harbor in 2015 and Privacy Shield in 2020. If the framework falls a third time, sites that depend on US tools will have to change again.

With Umami or Plausible on your own server, that question goes away. The visitor's browser talks to your server, the data stays on your disk, and no analytics vendor joins your list of processors. Our Amsterdam and Dublin locations keep the data inside the EU. If your visitors are mostly in Kosovo or the wider Balkans, a server in Prishtina keeps the data in the country and close to your readers, and the setup below works the same way there.

Umami vs Plausible, measured side by side

We installed both on Debian 13 in two identical lab machines on our Amsterdam test server, each limited to 2 vCPUs and 3 GB of RAM, with Docker 29.9.0 and Compose v5.6.0. Every number in this table comes from that lab unless a source is linked.

Umami 3.4.0Plausible CE v3.2.1
LicenceMITAGPLv3
Containers2: Umami (Next.js) and PostgreSQL 173: Plausible (Elixir), PostgreSQL 16 and ClickHouse 24.12
RAM at idle229 MB (193 app + 36 database)697 MB (409 app + 77 PostgreSQL + 211 ClickHouse)
RAM after 1,000 pageviews291 MB705 MB
Docker images on disk1.89 GB1.40 GB
First start, downloads included40 seconds41 seconds
Tracking script4.8 KB, 2.3 KB gzipped6.2 KB, 2.6 KB gzipped
1,000 test pageviews, 10 at a time12.5 seconds6.4 seconds
Visitor hash resetsMonthly by default, daily if you set itDaily
A plain curl requestDropped as a botCounted, with "curl" as the browser
First loginadmin / umami, change it at onceYou register the first account; the sign-up page then closes

Two results surprised us. First, Umami's images take more disk than Plausible's, although Plausible needs three times the RAM. Second, bot filtering differs: Umami answered our curl test with {"beep":"boop"} and stored nothing, while Plausible stored it. Plausible says CE has only "basic" bot filtering and the cloud version adds more (Plausible). Real browsers counted correctly in both.

On features, older comparisons say Umami has no funnels. That is out of date: Umami 3.4.0's release notes list assistant tools for its funnels, goals, journeys, retention and revenue reports. Plausible CE has goals and custom events, but funnels, ecommerce revenue goals, SSO and the Sites API are cloud-only. Most of Plausible's extra memory goes to ClickHouse, a database built for counting huge numbers of events, which used 211 MB on its own at idle in our lab.

Which server size fits

Going by the 291 MB peak we measured, Umami should fit on a 1 GB VPS Nano next to a small website. Plausible needs the 2 GB of a VPS Micro at the very least, and a VPS Mini with 4 vCPUs and 4 GB is the comfortable choice if the same server also runs your site. After 1,000 pageviews, Plausible's ClickHouse volume was 4 MB and Umami's PostgreSQL volume 68 MB, mostly the empty database itself, so disk space is rarely the limit. If traffic grows, you can move to a bigger plan from the client area with a short reboot.

Step 1: Docker and a normal user

Both tools run with Docker Compose, a tool that starts several containers from one file. Log in to a fresh Debian 13 server as root and install Docker from Docker's own repository:

# as root
apt-get update
apt-get install -y ca-certificates curl git
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
. /etc/os-release
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $VERSION_CODENAME stable" > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker --version
useradd -m -s /bin/bash -G docker stats
su - stats

We got Docker version 29.9.0. The last two lines create a user called stats that can run Docker and switch to it. Everything from here on runs as that user; exit takes you back to root. Our guide to Docker containers on a VPS explains the basics if Docker is new to you.

No firewall change is needed. Both setups below publish their ports on 127.0.0.1 only, so nothing is reachable from the internet until you put a reverse proxy in front. That matters with Docker, because ports it publishes on all addresses skip ufw rules (Docker docs).

Step 2a: install Umami

Create a folder and a file with two random secrets:

# as the stats user
mkdir -p ~/umami && cd ~/umami
cat > .env <<EOF
APP_SECRET=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -hex 16)
EOF
chmod 600 .env

Now the Compose file. It is based on Umami's own example, with the version pinned, the port limited to the server itself and the daily salt switched on:

# as the stats user, in ~/umami
cat > compose.yaml <<'EOF'
services:
  umami:
    image: ghcr.io/umami-software/umami:3.4.0
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:${POSTGRES_PASSWORD}@db:5432/umami
      APP_SECRET: ${APP_SECRET}
      SALT_ROTATION: day
    depends_on:
      db:
        condition: service_healthy
    init: true
    restart: always
  db:
    image: postgres:17-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - umami-db:/var/lib/postgresql/data
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U umami -d umami"]
      interval: 5s
      timeout: 5s
      retries: 5
volumes:
  umami-db:
EOF
docker compose up -d
curl -s http://127.0.0.1:3000/api/heartbeat

Give it 20 to 40 seconds, then the last command prints {"ok":true}. If it prints nothing, wait and run it again. Note the image tag is 3.4.0 without a "v"; v3.4.0 does not exist and fails with "manifest unknown". docker compose logs umami should show "All migrations have been successfully applied".

To open the dashboard before you have a domain, run this on your own computer with the login you normally use, keep it open, and browse to http://localhost:3000. It forwards port 3000 on your computer to port 3000 on the server, through SSH:

# on your own computer
ssh -N -L 3000:127.0.0.1:3000 root@YOUR_SERVER_IP

Log in as admin with the password umami, change the password straight away (the Umami docs say the same), and add your website. Umami then shows a website ID, a long code like 85453e04-cce0-..., which goes into the tracking script.

Step 2b: install Plausible Community Edition

Plausible ships its own Compose setup in a Git repository. Clone the release tag:

# as the stats user
git clone -b v3.2.1 --single-branch https://github.com/plausible/community-edition plausible-ce
cd plausible-ce
cat > .env <<EOF
BASE_URL=https://stats.example.com
SECRET_KEY_BASE=$(openssl rand -base64 48)
HTTP_PORT=8000
EOF
chmod 600 .env
cat > compose.override.yml <<'EOF'
services:
  plausible:
    ports:
      - 127.0.0.1:8000:8000
EOF
docker compose up -d
curl -s http://127.0.0.1:8000/api/health

Replace stats.example.com with the address you will really use. BASE_URL must match the address people type, so set up DNS and the reverse proxy (next section) before you register. In our lab we used a local test hostname instead. After about 40 seconds (run the curl line again if it prints nothing), the health check printed:

{"sessions":"ok","postgres":"ok","clickhouse":"ok","sites_cache":"ok"}

Open your BASE_URL, register the first account, then add your site by its bare domain and pick a reporting timezone. Plausible then shows its snippet. Once the first account exists, the sign-up page closes: in our lab, /register answered with a redirect to /login.

ClickHouse needs a CPU with SSE 4.2 support. grep -o -m1 sse4_2 /proc/cpuinfo prints sse4_2 when the server has it, as our lab server did.

Step 3: HTTPS and a real address

Point a DNS record such as stats.example.com at your server and put a reverse proxy in front of the local port: 127.0.0.1:3000 for Umami or 127.0.0.1:8000 for Plausible. A reverse proxy is a small web server that accepts HTTPS from visitors and passes the request on. Our guide to Caddy, Nginx and Traefik with free SSL shows the full setup. We could not test real certificates in our lab, because that needs a public domain.

Step 4: add the script and prove a pageview counts

Paste the snippet into the <head> of every page. For Umami it looks like this:

<!-- in your website's HTML -->
<script defer src="https://stats.example.com/script.js" data-website-id="YOUR-WEBSITE-ID"></script>

Plausible's snippet is two script tags with a per-site file name, so copy it from the site's installation page rather than typing it. Test on the real hostname of your site, the one you registered in the dashboard.

We tested with a plain HTML page on a local test hostname, loaded in headless Chromium with a normal desktop user agent. Both tools counted the visit. Plausible also stored an "engagement" event, which it uses to measure time on page. You can send a test pageview from the server itself with curl. Set a browser user agent, or Umami will drop it as a bot:

# as the stats user: one test pageview to Umami
curl -s -X POST http://127.0.0.1:3000/api/send -H 'Content-Type: application/json' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36' -d '{"type":"event","payload":{"website":"YOUR-WEBSITE-ID","hostname":"shop.example.test","url":"/pricing","title":"Pricing","language":"en-US","screen":"1920x1080","referrer":""}}'

# one test pageview to Plausible
curl -s -i -X POST http://127.0.0.1:8000/api/event -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36' -H 'Content-Type: application/json' -d '{"name":"pageview","url":"http://shop.example.test/pricing","domain":"shop.example.test"}'

Use your own website ID and domain. Umami answers with a JSON line containing a sessionId; Plausible answers HTTP/1.1 202 Accepted and ok. Then look at the raw data in the database, which is the surest sign that it arrived:

# as the stats user, in ~/umami
docker compose exec -T db psql -U umami -d umami -c "select url_path, count(*) from website_event group by 1;"

# as the stats user, in ~/plausible-ce
docker compose exec -T plausible_events_db clickhouse-client -q "SELECT pathname, count() AS views FROM plausible_events_db.events_v2 GROUP BY pathname FORMAT PrettyCompact"

In our lab, Umami showed / and /pricing once each, and its stats API reported 2 pageviews from 1 visitor: the browser visit and the curl test came from the same IP and user agent, so they shared one hash. ClickHouse listed / twice, because the engagement event is stored under the same page as the pageview. Plausible needs a few seconds to write events to ClickHouse, so run its query again if it comes back empty.

Plausible Cloud or your own server?

Plausible's prices in US dollars, per month, from plausible.io on 9 October 2026:

Monthly pageviewsStarterGrowthBusiness
10,000$9$14$19
100,000$19$29$39
1 million$69$104$139
10 million$169$254$339

Yearly billing gives two months free, and there is a 30-day trial. The cloud service is hosted in the EU and includes the features CE lacks, plus backups and upgrades handled for you. If you have one small site and want zero maintenance, it is a fair deal.

Self-hosting wins when you run several sites, when traffic is high, or when the analytics can share a server you already pay for. The software costs nothing and there is no pageview limit. The price is your time: you install updates, watch the disk and keep backups. A restic backup to a second server covers the database volumes, and Uptime Kuma can watch /api/heartbeat or /api/health for you.

Frequently asked questions

Is Umami or Plausible better for a small VPS?

Umami. In our lab it used about 230 MB of RAM at idle and under 300 MB after 1,000 pageviews, so it fits on a 1 GB server next to a website. Plausible Community Edition used about 700 MB because it runs ClickHouse, and its README recommends at least 2 GB of RAM.

Do Umami and Plausible use cookies?

No. Neither tracking script sets a cookie, which we confirmed by checking the HTTP headers. Both count unique visitors with a hash of the IP address, user agent and a rotating salt. Plausible rotates the salt daily; Umami rotates it monthly by default and daily with SALT_ROTATION=day.

Do I need a cookie banner for Plausible or Umami?

Often not, but it depends on your country. The EDPB says tracking scripts fall under the ePrivacy consent rule even without cookies. Regulators such as France's CNIL exempt audience measurement that is limited to one site, not combined with other data and open to objection. Self-hosted Umami or Plausible fits those conditions well. Mention it in your privacy policy either way.

Is Google Analytics 4 legal in the EU?

Transfers of EU data to certified US companies such as Google have been allowed since the EU-US Data Privacy Framework was adopted on 10 July 2023. The EU General Court upheld it in September 2025, but an appeal was pending in October 2026. GA4 also uses cookies, so it needs consent under the ePrivacy rules.

What is the difference between Plausible Cloud and Community Edition?

Community Edition is the free, self-hosted version under AGPLv3, released twice a year. Plausible Cloud costs from $9 a month and adds funnels, ecommerce revenue goals, SSO, the Sites API, stronger bot filtering and managed hosting in the EU.

How much disk space does self-hosted analytics need?

Plan for about 2 GB for the Docker images and some room for data. In our lab, Umami's images took 1.89 GB and Plausible's 1.40 GB. After 1,000 pageviews, Plausible's ClickHouse data took 4 MB and Umami's PostgreSQL volume 68 MB, most of it the empty database. A 20 GB NVMe disk is enough for either tool and a small website.

Your numbers, your server

For a light setup, start with Umami on a VPS Nano or Micro. If you want Plausible's dashboard, give it at least the 2 GB of a VPS Micro, or a VPS Mini when the website runs on the same server. RS Computers runs KVM servers in Amsterdam, Dublin and Prishtina, all with NVMe storage, unmetered traffic and their own IPv4 and IPv6 addresses. Availability by city is on the plans page. If you would rather have us install Umami or Plausible for you, message us on Telegram and we will quote the job.

← All articles

Chat on Telegram