itsez.dev
๐Ÿ“–Tutorial

How to install Umami on a VPS

2026-07-30ยท3 min readยทAnalytics

Umami is a lightweight analytics platform designed to provide useful website metrics without the tracking profile of many hosted tools. This guide deploys Umami with PostgreSQL and Docker Compose, adds HTTPS and explains how to connect the first website.

Prerequisites

Use Ubuntu 22.04 or 24.04 with SSH, a public IP and at least 1 GB of RAM for a small analytics instance. Create an A record such as analytics.example.com and allow ports 80 and 443. You also need a backup destination and a long random application secret.

Umami stores event data in PostgreSQL, so disk usage depends on traffic and retention. Do not expose PostgreSQL to the internet. Only the reverse proxy should be public.

Step 1, Connecting to your server

Connect and prepare a dedicated directory:

ssh root@SERVER_IP
apt update && apt upgrade -y
apt install -y ca-certificates curl
mkdir -p /opt/umami
cd /opt/umami
chmod 750 /opt/umami

Check that ports 80, 443 and the internal application port are not occupied. Keep the Compose file and .env readable only by administrators.

Step 2, Installing Docker and Docker Compose

Install Docker Engine and the Compose plugin using Docker's current Ubuntu instructions. Confirm the installation:

docker --version
docker compose version
systemctl enable --now docker

Use the current Compose syntax and a supported package source. Keep the host patched before exposing the analytics endpoint.

Step 3, Running Umami with Docker Compose

Create .env with values that do not appear anywhere else:

POSTGRES_DB=umami
POSTGRES_USER=umami
POSTGRES_PASSWORD=REPLACE_WITH_A_RANDOM_VALUE
APP_SECRET=$(openssl rand -hex 32)
DATABASE_URL=postgresql://umami:REPLACE_WITH_A_RANDOM_VALUE@db:5432/umami

This is critical โ€” without APP_SECRET, authentication tokens are not properly secured. Generate it with openssl rand -hex 32 and never share it. The password in DATABASE_URL must match POSTGRES_PASSWORD, with URL encoding if your generated value contains reserved characters. Create compose.yaml:

services:
  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data

  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    restart: unless-stopped
    depends_on:
      - db
    environment:
      DATABASE_URL: ${DATABASE_URL}
      APP_SECRET: ${APP_SECRET}
    ports:
      - "127.0.0.1:3000:3000"

volumes:
  db_data:

Set PostgreSQL timezone to UTC. Umami expects UTC for correct analytics aggregation.

Start and inspect the stack:

docker compose up -d
docker compose ps
docker compose logs --tail 100 umami

Pin tested image tags before using the deployment for important reporting.

Step 4, Configuring the reverse proxy

Forward analytics.example.com from Caddy, Nginx or another supported proxy to 127.0.0.1:3000. Terminate TLS at the proxy, preserve the original host and protocol headers and keep port 3000 private. The analytics script must load over HTTPS when the website uses HTTPS, otherwise browsers can block it as mixed content.

If you use a host firewall, allow SSH, 80 and 443 only. Test certificate renewal and check that the proxy sends the correct Host header to Umami. Behind a CDN or proxy, set CLIENT_IP_HEADER and FORCE_SSL environment variables in the Umami service for correct IP geolocation.

Step 5, First access and initial setup

Open https://analytics.example.com and complete the first login. Change the default admin credentials (admin / umami) immediately. Create a website entry, copy the generated tracking snippet and add it to the site you want to measure.

Load the site in a private browser window and confirm that a page view appears. Check the hostname and timezone before inviting other users. Avoid collecting data you do not need, and document any consent requirements that apply to your audience.

Maintenance

Back up PostgreSQL and APP_SECRET together. Keep retention under control and monitor the database volume with df -h and PostgreSQL metrics. Update Umami after reviewing release notes, run the migration in the supported way and verify that reports still load.

If events stop arriving, inspect the browser network request, proxy logs and Umami logs in that order. Do not delete the database volume to fix a tracking problem.

Tools mentioned

Umami

โ†—

Clean, privacy-minded website analytics with straightforward reports.

FreemiumNo cardOSS

Free cloud plan: up to 3 websites, 100k events/month and 6-month retention; self-hosting is unlimited.

ABOUT US

Honest, independent, no fluff.

No paid placements. Just a clear look at what this does, what it costs, and what to know before you commit.

Read moreโ†’

FAQ

Questions, answered.

What does Umami need to run?๏ผ‹

A small installation needs a Linux VPS, Docker, PostgreSQL storage and a domain behind HTTPS. Give it more memory as traffic and retention grow.

Can Umami run without a public domain?๏ผ‹

You can test it on a private address, but a public HTTPS URL is the practical choice for receiving analytics from websites.

How do I back up Umami?๏ผ‹

Back up the PostgreSQL database and the application secret together, then test restoring both on another host.