
Self-hosting your analytics means complete data ownership. No third party ever sees your visitor data. No monthly fees that scale with traffic. No terms of service that change overnight.
Umami is a free, open-source analytics tool designed exactly for this. It’s lightweight, privacy-focused, and runs on any VPS with Node.js and a database. If you have a server running WordPress, you likely have enough resources to run Umami alongside it.
This guide covers a complete production setup: from provisioning a VPS to seeing your first real-time visitor.
Why Self-Host Your Analytics
Cloud analytics services — even privacy-focused ones like Plausible and Fathom — still mean sending your data to someone else’s servers. Self-hosting eliminates that entirely.
- Zero data sharing. Visitor data never leaves your server. There’s no data processing agreement to worry about because you are the data processor.
- No traffic-based pricing. Whether you get 1,000 or 10 million pageviews, your only cost is the VPS. A $5-10/month server handles most sites easily.
- Full GDPR compliance. You control exactly where data is stored. Pick an EU datacenter and your data physically stays in the EU.
- No vendor lock-in. If Umami changes direction, you have the code and the database. Fork it or switch without losing historical data.
The trade-off is maintenance: you handle updates, backups, and server uptime. With Docker and the setup below, that’s roughly 30 minutes per month.
Prerequisites
You’ll need:
- A VPS with at least 1 GB RAM and 1 CPU core (2 GB recommended). Providers like Hetzner, DigitalOcean, or Vultr work well. A €4-5/month server from Hetzner (EU-based) is ideal for GDPR compliance.
- Docker and Docker Compose installed on the server.
- A domain or subdomain for your analytics dashboard (e.g.,
analytics.yourdomain.com). - Basic SSH access and comfort with the command line.
Step 1: Set Up Your VPS

SSH into your server and install Docker if it’s not already there:
# Install Docker (Ubuntu/Debian)
curl -fsSL https://get.docker.com | sh
# Install Docker Compose
sudo apt install docker-compose-plugin
# Verify installation
docker --version
docker compose version
Create a directory for your Umami installation:
mkdir -p /opt/umami
cd /opt/umami
Step 2: Create the Docker Compose File
Create a docker-compose.yml file with Umami and PostgreSQL:
# /opt/umami/docker-compose.yml
version: '3'
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://umami:your-secure-password@db:5432/umami
APP_SECRET: replace-with-random-64-char-string
depends_on:
db:
condition: service_healthy
restart: always
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: your-secure-password
volumes:
- umami-db-data:/var/lib/postgresql/data
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami"]
interval: 5s
timeout: 5s
retries: 5
volumes:
umami-db-data:
Important: Replace your-secure-password with a strong password (use openssl rand -hex 32 to generate one). Replace APP_SECRET with a random string (openssl rand -hex 32 again). These two values should be different.
Step 3: Start Umami
cd /opt/umami
docker compose up -d
Docker pulls the images and starts both containers. First startup takes 1-2 minutes while PostgreSQL initializes and Umami creates its database tables.
Verify everything is running:
docker compose ps
You should see both umami and db containers with status “Up”. Umami is now accessible at http://your-server-ip:3000.
Step 4: Set Up a Reverse Proxy with SSL
Running Umami on port 3000 without SSL isn’t suitable for production. Set up Nginx as a reverse proxy with Let’s Encrypt SSL.
First, point your subdomain DNS (e.g., analytics.yourdomain.com) to your server’s IP address. Then install Nginx and Certbot:
# Install Nginx and Certbot
sudo apt install nginx certbot python3-certbot-nginx
Create an Nginx server block:
# /etc/nginx/sites-available/analytics
server {
server_name analytics.yourdomain.com;
location / {
proxy_pass http://localhost: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;
}
}
# Enable the site and get SSL certificate
sudo ln -s /etc/nginx/sites-available/analytics /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d analytics.yourdomain.com
Certbot automatically configures HTTPS and sets up auto-renewal. Your Umami dashboard is now available at https://analytics.yourdomain.com.
Step 5: Log In and Add Your Website

Open your Umami dashboard and log in with the default credentials:
- Username: admin
- Password: umami
Change the default password immediately after your first login. Go to Settings → Profile to update it.
Then add your website:
- Go to Settings → Websites → Add website
- Enter your domain name and a display name
- Click Save
- Click the Edit icon next to your site, then Tracking code
- Copy the tracking script
The tracking script looks like this:
<script defer src="https://analytics.yourdomain.com/script.js" data-website-id="your-website-id"></script>
Step 6: Add the Tracking Script to WordPress
There’s no official Umami WordPress plugin, but adding the script is simple. The cleanest approach is through your child theme’s functions.php:
add_action('wp_head', function() {
echo '<script defer src="https://analytics.yourdomain.com/script.js" data-website-id="your-website-id"></script>';
});
Alternatively, use a plugin like Insert Headers and Footers (by WPCode) to paste the script into the header without editing theme files.
After adding the script, visit your site in an incognito window and check the Umami dashboard. You should see a real-time visitor within seconds.
Maintenance and Backups

Self-hosting means you’re responsible for keeping things running. Here’s the minimum maintenance routine:
Updating Umami
Umami releases updates regularly. To update:
cd /opt/umami
docker compose pull
docker compose up -d
This pulls the latest image and restarts the container. Downtime is typically under 10 seconds. Run this monthly or when security patches are announced.
Database Backups
Back up your PostgreSQL data regularly. A simple cron job works:
# Add to crontab: daily backup at 3 AM
0 3 * * * docker exec umami-db-1 pg_dump -U umami umami | gzip > /opt/umami/backups/umami-$(date +\%Y\%m\%d).sql.gz
Keep at least 7 days of backups. For critical sites, copy backups to an offsite location using rclone or rsync.
Monitoring Uptime
If your analytics server goes down, you lose data for that period (it can’t be recovered). Use a free uptime monitor like UptimeRobot or Better Stack to get alerted if the dashboard becomes unreachable.
Performance Tuning
For sites with over 100K monthly pageviews, consider these optimizations:
- Increase PostgreSQL memory. Add
shm_size: '256mb'to the db service in your Docker Compose file. - Enable WAL mode. Improves write performance for high-traffic sites.
- Use SSD storage. If your VPS uses HDD, migrate to SSD. The database does heavy random reads.
- Separate servers. For very high traffic (1M+ monthly), run the database and Umami on separate VPS instances.
For most WordPress sites, the default configuration handles traffic comfortably. A 2 GB VPS from Hetzner (€4.50/month) can process millions of events per month.
FAQ
How much server resources does Umami use?
At idle, Umami uses roughly 150-200 MB RAM and minimal CPU. Under load (thousands of concurrent visitors), RAM usage stays under 500 MB. The PostgreSQL database is the heavier component — allocate at least 512 MB for it on busy sites.
Can I run Umami on the same server as WordPress?
Yes, and many people do. If your WordPress server has at least 2 GB total RAM and runs on Docker or has Docker installed alongside, Umami can share the server. Just make sure Umami’s port (3000) doesn’t conflict with other services.
Is Umami Cloud worth it instead of self-hosting?
Umami Cloud is free for up to 100K events per month. If you don’t want server maintenance and your traffic fits the free tier, Cloud is the easier choice. Self-hosting makes sense when you need full data control, have high traffic, or want to avoid any external data processing.
How do I migrate from Google Analytics to Umami?
There’s no direct import — GA and Umami use completely different data models. Install Umami alongside GA, run both for 30 days to build baseline data, then remove GA. Your historical GA data stays accessible in Google’s interface. For a detailed process, see our guide to migrating from Google Analytics.
Start Tracking on Your Own Terms
Self-hosted Umami gives you everything most websites need from analytics — pageviews, referrers, device info, custom events — without sending a single byte of visitor data to anyone else. The setup takes under an hour, the ongoing cost is a few dollars per month for a VPS, and the maintenance is minimal.
If self-hosting feels like too much, Plausible’s WordPress plugin gets you privacy-first analytics in under 10 minutes with zero server management. Both are excellent choices — pick the one that matches your comfort level with infrastructure.
