Blog · Deploy guides

How to self-host Umami in 2026: its Compose file, two commands and HTTPS

By the Pethost team · · 7 min read

You want Umami's analytics on a server of your own, with its Postgres, at an address with HTTPS, and without setting up a proxy or certificates. Umami ships a Docker Compose file, and on Pethost a Compose file is a project. Change two things in it, run pethost deploy, then give Umami its address with one more command. Umami and its database started in 49 seconds.

In short
  • The file is Umami's own: docker-compose.yml from its repository, with Umami and Postgres 15.
  • Two edits: put your own secrets in place of the two placeholders, and delete the two ports lines. HTTPS comes through the address, so the port is not published as well.
  • Two commands: pethost deploy, then pethost domain add umami.yourname.pethost.app umami:3000.
  • The data stays: Postgres keeps it in a volume that the nightly backup includes. A new version of Umami is one changed tag and one deploy.
  • The price: €9.99 a month for a machine of 2 vCPU, 3 GB and 30 GB. Umami and Postgres took about 220 MB of its memory. There is no free tier.

What you need to self-host Umami in 2026

Three things: Umami's Compose file, the pethost command and a Pethost account.

The file is in Umami's repository. Put it into a folder of its own, whose name becomes the project's name:

mkdir umami && cd umami
curl -O https://raw.githubusercontent.com/umami-software/umami/master/docker-compose.yml

The command is one program, installed by one line. Every command it has is in the CLI's reference.

curl -fsSL https://pethost.dev/install.sh | sh      # macOS, Linux
irm https://pethost.dev/install.ps1 | iex           # Windows, in PowerShell

The account needs a plan. If you are not signed in, pethost deploy opens your browser and signs you in. If you have no plan yet, it shows you where to choose one, and waits.

Two edits to Umami's docker-compose.yml

The service umami begins like this in the file:

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

First, the secrets. Run openssl rand -hex 32 twice and put one result in place of each placeholder. They stay in the file, so every later deploy starts Umami with the same ones.

Second, the port. Delete the two lines ports: and - "3000:3000". On your own server they open port 3000 to the world over plain HTTP. On Pethost visitors reach Umami through its address, over HTTPS, and the proxy on your machine passes each request to port 3000 inside the project. A port that is published and also behind an address would answer both ways, so the machine refuses that pair and names the line:

✗ services.umami.ports[0]: port 3000 is published, and the route umami.sam.pethost.app/ sends to it: the proxy serves it over HTTPS, and published it also answers plain HTTP past the proxy. Remove it from ports
  Nothing changed.

Nothing else in the file changes. The database's volume, the health checks and depends_on run as Umami wrote them.

Deploy Umami with pethost deploy

Run pethost deploy in the folder. This is the whole screen:

$ pethost deploy
Name it [umami]:    it will live at https://umami.sam.pethost.app
✓ Packed 1 file, 1 KB
✓ Uploaded straight to your machine
✓ Started in 49 s
  · deployed docker-compose.yml as compose.yaml
  More than one port listens, so no address was given. Give it to the one that is the site:
    pethost domain add umami.sam.pethost.app db:5432
    pethost domain add umami.sam.pethost.app umami:3000
Wrote .pethost (commit it). Next:   pethost logs -f

Both services run now. The machine saw two ports that listen, Postgres on 5432 and Umami on 3000, and does not guess which one is the site. It prints the command for each. Take Umami's:

$ pethost domain add umami.sam.pethost.app umami:3000
umami (.pethost)
✓ umami.sam.pethost.app → umami:3000
https://umami.sam.pethost.app

Postgres gets no address and no published port: only Umami reaches it, by the name db. This is the project after that:

$ pethost
umami · https://umami.sam.pethost.app
db	healthy	since 2026-10-10T12:20:23Z	listens on 5432	memory 31 MB
umami	healthy	since 2026-10-10T12:20:29Z	listens on 3000	memory 191 MB
2 services run · last deploy succeeded 2026-10-10T12:26:43Z

Sign in and add your website

Open the address. A new Umami has one account, the username admin with the password umami. Sign in and change that password before anything else. Then add your website in Umami's settings and put its tracking script on your pages. The script comes from your own address:

<script defer src="https://umami.sam.pethost.app/script.js" data-website-id="…"></script>

We asked the deployed Umami what a browser asks. The login page, /api/heartbeat and /script.js each answered 200, and the default account signed in.

To use a name of your own, such as stats.example.com, run pethost domain add stats.example.com umami:3000. It prints the one DNS record to make, a CNAME to your machine's name, and the certificate comes by itself once the name resolves.

Where the Umami data is, and how it is backed up

Umami keeps accounts, websites and every pageview in Postgres, and the Compose file gives Postgres a volume. The machine keeps that volume through restarts and deploys, and the nightly backup includes it:

$ pethost volume
umami (.pethost)
umami-db-data	47 MB	db:/var/lib/postgresql/data	backed up 2026-10-10T12:19:40Z

We restarted the project with pethost restart and signed in again with the same account. pethost backup lists the snapshots, and pethost backup restore puts one back. For a look into the database from your laptop, pethost tunnel db brings its port to localhost without opening it to anyone else.

Update Umami to a new version

The file's tag is latest. To choose the moment of an update yourself, name a version in docker-compose.yml and deploy again. We went from 3.3.1 to 3.4.0 this way:

    image: ghcr.io/umami-software/umami:3.4.0
$ pethost deploy
umami (.pethost)
✓ Packed 2 files · uploaded · started in 44 s
  · deployed docker-compose.yml as compose.yaml
  · kept the project's x-pethost
  It answers 200.
https://umami.sam.pethost.app

The address stayed, the data stayed, and the account signed in as before. Read Umami's release notes first, and take a snapshot with pethost backup now before a large update: a rollback puts the earlier Compose file back, and a volume's data is not part of a version.

What you get for the price

Pethost is €9.99 a month for everything you host, on 2 vCPU, 3 GB of memory and 30 GB of disk. Umami and its Postgres took about 220 MB of that memory, so the same machine has room for the sites Umami counts and for your other projects, such as an RSSHub beside it. There is no fee per project, and the database is part of the same price. Nothing is metered by pageview.

What is already done on it: HTTPS with certificates that renew themselves, nightly backups kept for 14 days, SSH into any container, and a Compose project that runs from its own file. The machine is in the EU and always on, so the tracking script never waits for a cold start. The plans are on the pricing part of the first page.

What each project takes. The capacity page: every project with its memory, CPU and disk.
The Pethost panel's capacity page: each project with its memory, CPU and disk.

Pethost is the best pick for

  • People who want their analytics on their own server, without looking after the server
  • Solo developers with several sites to count and one bill to pay
  • People whose agent deploys for them: Claude Code or Codex deploys the Compose file and reads its logs
  • Small teams who keep their visitors' data in the EU

Look elsewhere if

  • Your sites have so many visitors that the analytics need a database cluster of their own

Questions

Can I self-host Umami with Docker Compose without a server to manage?

Yes. On Pethost Umami's own docker-compose.yml is the project: delete its two ports lines, set the two secrets, run pethost deploy and give Umami its address with pethost domain add. HTTPS, the proxy and the backups are already there.

Why do I remove the ports lines from Umami's Compose file?

They publish port 3000 over plain HTTP. On Pethost visitors come through the project's address over HTTPS, and the proxy reaches port 3000 inside the project, so the port is not published as well. The machine refuses an address for a port that is also published.

What is the default Umami login after a new install?

The username admin and the password umami. Change the password in Umami as soon as you have signed in.

How much memory does self-hosted Umami need?

On our test machine Umami 3.4.0 took 191 MB and its Postgres 31 MB, with one website and little traffic. A Starter machine has 3 GB.

How do I update self-hosted Umami?

Change the image's tag in docker-compose.yml to the new version and run pethost deploy. The data in Postgres stays: we went from 3.3.1 to 3.4.0 this way and signed in as before.

What does it cost to self-host Umami on Pethost?

€9.99 a month for the Starter machine of 2 vCPU, 3 GB and 30 GB, with no fee per project and nothing counted per pageview: the same machine runs your sites and other apps. There is no free tier. Prices are without VAT.

The screens are deploys of the Compose file in Umami's repository, with Umami 3.4.0, Postgres 15.19 and pethost 0.2.1, on a test machine of ours. The account in them is the example one, sam.

  1. Umami: installation
  2. Umami: docker-compose.yml
  3. Umami: login
  4. pethost, the command line of Pethost

Put your projects online today

A machine of your own, as many projects as fit, one flat price. Nothing metered, nothing billed on top.

Host all your projects for €9.99/mo