# Umami

Web analytics without cookies, stored in a Postgres database that you run.

- Replaces: [Google Analytics](https://openlogs.fyi/alternatives/google-analytics)
- Summary: Hosted web analytics, such as Google Analytics.
- Stack: Node.js (runtime), Next.js (framework), PostgreSQL (database)
- Deployment: docker_compose, docker, manual
- License: MIT (osi) [source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/LICENSE)
- Business model: unknown. The README says Umami runs self-hosted or in the cloud. We did not check what the cloud plan adds, so the business model stays unknown. ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md), read 2026-10-21)
- Difficulty: medium. Two services: the app and a Postgres database in a named volume that you back up. You must replace the placeholder secrets before the first start.
- Requirements: not stated
- Repository: [umami-software/umami](https://github.com/umami-software/umami)

## Install

1. Docker with the Compose plugin ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md))

   ```text
   A host with Docker and the Docker Compose plugin. The compose file starts its own PostgreSQL container.
   ```

2. Save the compose file as docker-compose.yml ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/docker-compose.yml))

   ```yaml
   ---
   services:
     umami:
       image: ghcr.io/umami-software/umami:latest
       ports:
         - "3000:3000"
       environment:
         DATABASE_URL: postgresql://umami:umami@db:5432/umami
         APP_SECRET: replace-me-with-a-random-string
         # Required for two-factor authentication, generate with: openssl rand -hex 32
         TWO_FACTOR_ENCRYPTION_KEY: replace-me-with-a-64-character-hex-string
       depends_on:
         db:
           condition: service_healthy
       init: true
       restart: always
       healthcheck:
         test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
         interval: 5s
         timeout: 5s
         retries: 5
     db:
       image: postgres:15-alpine
       environment:
         POSTGRES_DB: umami
         POSTGRES_USER: umami
         POSTGRES_PASSWORD: umami
       volumes:
         - umami-db-data:/var/lib/postgresql/data
       restart: always
       healthcheck:
         test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
         interval: 5s
         timeout: 5s
         retries: 5
   volumes:
     umami-db-data:
   ```

3. Set the two secrets in the file ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/docker-compose.yml))

   ```text
   The compose file has two placeholder values: APP_SECRET (a random string) and TWO_FACTOR_ENCRYPTION_KEY (64 hex characters; the file says to generate it with: openssl rand -hex 32). Replace both before the first start.
   ```

4. Start it ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md))

   ```bash
   docker compose up -d
   ```

5. Check that it answers ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/docker-compose.yml))

   ```text
   Open http://localhost:3000. The compose file health check calls http://localhost:3000/api/heartbeat inside the container.
   ```

Compose file check: config_ok on 2026-10-21.

## Gotchas and maintenance

### Gotchas

- The compose file has placeholder secrets and a weak database password: APP_SECRET and TWO_FACTOR_ENCRYPTION_KEY are placeholders ("replace-me..."). The database user and password in the file are both "umami". ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/docker-compose.yml), checked 2026-10-21)
- The image tag is latest: The compose file uses ghcr.io/umami-software/umami:latest, so a pull can move to a new version without notice. ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/docker-compose.yml), checked 2026-10-21)
- Default login from the README: The README says the first build creates a login user named admin with the password umami. ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md), checked 2026-10-21)

### Upgrades

- Upgrade the Docker install: The README gives these steps: docker compose pull, then docker compose up --force-recreate -d. ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md), checked 2026-10-21)

### Requirements

- Versions for a non-Docker install: The README lists Node.js 18.18 or newer and PostgreSQL 12.14 or newer. ([source](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md), checked 2026-10-21)

### Signals

Computed from a GitHub snapshot taken 2026-10-21.

- Open issues and pull requests: 121
- Stars: 39494, forks: 8359
- Last push: 2026-10-20 (1 days ago)
- Latest release: v3.4.0 on 2026-09-17 (34 days ago)

## Sources

- [Repository: https://github.com/umami-software/umami](https://github.com/umami-software/umami)
- [License: https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/LICENSE](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/LICENSE)
- [Business model: https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/README.md)
- [Compose file: https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/docker-compose.yml](https://github.com/umami-software/umami/blob/e92fdab99508a8ed05249f6c5f07e140deab79e1/docker-compose.yml)

---
Canonical: https://openlogs.fyi/tools/umami  
Last updated: 2026-10-22
