Umami is an open-source, privacy-focused web analytics tool. It shows the essentials — visitors, pages, referrers, countries, browsers, devices and custom events — without cookies or personal data. It’s light: a Node.js app with PostgreSQL (or MySQL), so it runs comfortably on a small VPS alongside other services.
1. Requirements
- Docker and Docker Compose (install guide).
- A subdomain like
analytics.example.com. - About 512 MB–1 GB of RAM for the app and database.
2. Compose file
mkdir -p ~/umami && cd ~/umami
compose.yaml:
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
restart: unless-stopped
environment:
DATABASE_URL: postgresql://umami:${DB_PASSWORD}@db:5432/umami
APP_SECRET: ${APP_SECRET}
ports:
- "127.0.0.1:3000:3000"
depends_on:
db:
condition: service_healthy
db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- umami-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami -d umami"]
interval: 5s
timeout: 5s
retries: 5
volumes:
umami-db:
Image tags and variable names change between major versions — check the Umami docs for the version you deploy.
cat > .env <<EOF
DB_PASSWORD=$(openssl rand -base64 24)
APP_SECRET=$(openssl rand -hex 32)
EOF
chmod 600 .env
docker compose up -d
3. HTTPS
server {
listen 80;
server_name analytics.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d analytics.example.com
Forwarding the real client IP matters: Umami uses it (hashed, not stored) to count unique visitors and determine the country.
4. Change the default login immediately
Umami creates a default account — username admin, password umami. Log in at https://analytics.example.com and change the password right away (Settings → Profile), or create a new admin user and delete the default.
5. Add a website and the tracking script
Settings → Websites → Add website, enter the domain, then copy the tracking code:
<script defer src="https://analytics.example.com/script.js" data-website-id="your-website-uuid"></script>
Add it to the <head> of every page. Useful attributes:
data-domains="example.com"— only track on these domains (ignores staging/localhost).data-do-not-track="true"— respect the browser’s Do Not Track setting.data-auto-track="false"— disable automatic pageviews (for custom SPA tracking).
To reduce blocking by ad blockers, you can rename the script and endpoint with the TRACKER_SCRIPT_NAME and COLLECT_API_ENDPOINT environment variables, or proxy them through your main site.
6. Track events
Add a data attribute to any element:
<button data-umami-event="Signup button" data-umami-event-plan="pro">Sign up</button>
Or from JavaScript:
umami.track('Purchase', { value: 49, currency: 'USD' });
Events appear in the Events section, and you can build funnels and goals in recent versions.
7. Sharing and teams
Create a share URL to make a dashboard public (read-only), or add users and teams so colleagues and clients see only their sites.
8. Backups and updates
docker compose exec db pg_dump -U umami umami | gzip > umami-$(date +%F).sql.gz
Copy dumps off the server (automated backups). Update:
docker compose pull && docker compose up -d
Database migrations run automatically on start. For major version jumps, read the upgrade notes — some required migration steps.
Umami vs Plausible vs Matomo
| Umami | Plausible CE | Matomo | |
|---|---|---|---|
| Stack | Node.js + PostgreSQL/MySQL | Elixir + PostgreSQL + ClickHouse | PHP + MySQL |
| Resources | Light | Moderate (ClickHouse) | Moderate to heavy |
| Cookies | No | No | Optional |
| Features | Essentials + events, funnels | Essentials + goals, funnels | Very extensive (GA-like) |
| Best for | Many small sites on a small server | High-volume sites | Detailed marketing analytics |
Umami is one of the easiest self-hosted apps to run — a small Docker VPS can host it alongside your websites.