What is Umami?
Umami is a simple, fast and privacy-focused web analytics platform, often used as a Google Analytics alternative. It is open source under the MIT license, collects no personal data, sets no cookies and has a clean dashboard for pageviews, referrers, devices, locations and custom events. One instance can track any number of websites.
Requirements
- A Linux server with 1 vCPU and 1 GB of RAM.
- Docker Engine and Docker Compose v2.
- A domain name such as
stats.example.com, so the tracking script loads over HTTPS.
Step 1: Prepare the server
This guide assumes Ubuntu 24.04 with Docker installed. If you need Docker, follow the official install guide. Create a project folder:
mkdir -p ~/umami && cd ~/umami
Step 2: Create the Docker Compose file
This follows the official Compose file, which runs Umami with Postgres. Save as docker-compose.yml:
services:
umami:
image: ghcr.io/umami-software/umami:latest
restart: always
init: true
ports:
- "127.0.0.1:3000:3000"
environment:
DATABASE_URL: postgresql://umami:${POSTGRES_PASSWORD}@db:5432/umami
APP_SECRET: ${APP_SECRET}
TWO_FACTOR_ENCRYPTION_KEY: ${TWO_FACTOR_ENCRYPTION_KEY}
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/api/heartbeat"]
interval: 10s
timeout: 5s
retries: 5
db:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- umami-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami -d umami"]
interval: 5s
timeout: 5s
retries: 5
volumes:
umami-db-data:
Create .env in the same folder:
POSTGRES_PASSWORD=CHANGE_ME
APP_SECRET=CHANGE_ME
TWO_FACTOR_ENCRYPTION_KEY=CHANGE_ME
Generate each value with openssl rand -hex 32. Use hex for the database password so it is safe inside the DATABASE_URL. APP_SECRET signs login tokens, and TWO_FACTOR_ENCRYPTION_KEY (a 64-character hex string) encrypts two-factor secrets. The port is bound to 127.0.0.1 so the dashboard is only reachable through your HTTPS proxy. To pin a version instead of latest, pick a tag from the releases page.
Step 3: Start and open the app
docker compose up -d
docker compose logs -f umami
On first start Umami creates its database tables. Finish Step 4, then open https://stats.example.com, or test via an SSH tunnel with ssh -L 3000:127.0.0.1:3000 user@server. Sign in with the default credentials, username admin and password umami, then change the password straight away under Settings, Profile.
Add a website under Settings, Websites, then open its "Tracking code" tab. Paste the snippet into the <head> of your site:
<script defer src="https://stats.example.com/script.js" data-website-id="YOUR-WEBSITE-ID"></script>
Step 4: Put it behind HTTPS
With Caddy on the host:
stats.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3000
}
Caddy issues the certificate automatically and forwards the client IP, which Umami needs for location data. With Nginx Proxy Manager, create a proxy host for port 3000 and request a Let's Encrypt certificate. Ad blockers often block script.js on known analytics hosts; setting the TRACKER_SCRIPT_NAME environment variable to a custom name such as stats.js reduces that.
Backups and upgrades
Everything lives in Postgres. Dump it regularly:
docker compose exec -T db pg_dump -U umami umami | gzip > umami-$(date +%F).sql.gz
Store the dump off-site, along with your .env. Restore by piping the dump into psql on a fresh database.
Upgrade with:
docker compose pull && docker compose up -d
Umami applies database migrations automatically on start. For major versions, read the release notes first, because some major upgrades require a migration step.
Troubleshooting
- No data appears: the website ID in the snippet is wrong, or an ad blocker in your test browser blocks the script. Test in a private window without extensions.
- All visitors show the same location: the reverse proxy is not forwarding the client IP in
X-Forwarded-For. - Container restarts with a database error:
DATABASE_URLdoes not match the Postgres credentials, often because the password contains special characters. Use a hex password. - Cannot log in with admin/umami: the database was created by an earlier install with a different password. Reset it in the database or restore your backup.
Next steps
Track custom events with data-umami-event attributes, create teams to share dashboards, set up public share links for open stats, and add more websites to the same instance.
Spotted something out of date? Tell us and we will update the guide.