Application Stacks Azure

Umami on Ubuntu 24.04 on Azure User Guide

| Product: Umami on Ubuntu 24.04 LTS on Azure

Overview

This image runs Umami 2.20, the open source, privacy-friendly web analytics platform - a cookieless, self-hosted alternative to Google Analytics - on Ubuntu 24.04 LTS. Umami is built and run from /opt/umami on the Node.js 22 LTS runtime by an unprivileged umami system account under a systemd service that starts it on boot and restarts it on failure. A local PostgreSQL 16 database stores all analytics data.

Umami listens on the loopback address 127.0.0.1:3000 by design and is never exposed directly. nginx is installed as a reverse proxy on port 80 that forwards every request to Umami. Visitors reach the application on the standard HTTP port.

Umami ships with a well known default administrator login (admin / umami) and signs authentication tokens with an APP_SECRET. This image is secure by default: on the first boot of every deployed VM a one-shot service rotates the administrator password to a fresh per-VM value and generates a fresh APP_SECRET, then writes the password to /root/umami-credentials.txt (mode 0600, readable only by root). The default umami password never reaches a customer VM, and two VMs deployed from the same image never share a password.

The analytics data (page views, sessions, events, websites and users) lives in PostgreSQL with its data directory under /var/lib/postgresql on a dedicated Azure data disk - separate from the OS disk, independently resizable, and re-provisioned with every VM deployed from this image. Umami is fully self-hosted - your analytics data never leaves your VM.

What is included:

  • Umami 2.20 built from source at /opt/umami, run as the Next.js standalone server on loopback 127.0.0.1:3000
  • nginx reverse proxy on :80 in front of the application
  • PostgreSQL 16 with its data directory on a dedicated Azure data disk at /var/lib/postgresql
  • Per-VM administrator password and APP_SECRET generated at first boot, in a root-only file
  • umami.service, nginx.service and postgresql.service as systemd units, enabled and active
  • A fully security-patched Ubuntu 24.04 LTS base (phased updates included) at image build time
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2ms (2 vCPU / 8 GiB RAM) is a good starting point; scale up for higher traffic volumes. NSG inbound: allow 22/tcp from your management network and 80/tcp from your users (front port 80 with TLS for public exposure - see Enabling HTTPS).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Umami by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Review the dedicated database data disk on the Disks tab, then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name umami \
  --image <marketplace-image-urn> \
  --size Standard_B2ms \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

az vm open-port --resource-group <your-rg> --name umami --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

The application is three systemd services - the Umami Next.js server (loopback 127.0.0.1:3000), the nginx reverse proxy on port 80, and the PostgreSQL database:

systemctl is-active umami.service nginx.service postgresql.service
curl -s -o /dev/null -w 'heartbeat HTTP %{http_code}\n' http://127.0.0.1/api/heartbeat

All three services report active and the heartbeat endpoint returns 200.

Umami services, health endpoint and the dedicated database data disk

Step 5 - Retrieve your administrator password

On the first boot, a one-shot service generated a unique administrator password for this VM and rotated the token-signing secret. Read the credentials file (root only):

sudo cat /root/umami-credentials.txt

You will see the sign-in URL, the username admin, and the generated password. Keep this password somewhere safe.

Per-VM administrator credentials generated on first boot

Step 6 - Sign in to Umami

Open http://<vm-public-ip>/ in your browser. You are taken to the Umami sign-in page. Enter the username admin and the password from the credentials file, and sign in.

Umami sign-in

After signing in you land on the Umami dashboard. On a fresh VM there is no data yet - you add a website in the next step to start collecting analytics.

Umami dashboard

Change the administrator password from the default per-VM value once you are signed in: open the user menu (top right), choose Profile, and set a new password. You can also create additional users under Settings -> Users.

Step 7 - Add and track a website

  1. In the top navigation choose Settings, then Websites, then Add website.
  2. Give the website a Name and its Domain (for example example.com), and save.
  3. Open the website's menu and choose Edit (or the code / tracking-code action) to reveal the tracking code - a small <script> snippet that references /script.js on your Umami VM.

Adding and tracking a website in Umami

Copy the tracking snippet and paste it into the <head> of every page of your website. It looks like this (the data-website-id is unique to your website and the src host is your Umami VM):

<script defer src="http://<vm-public-ip>/script.js" data-website-id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"></script>

Once the script is live on your site and visitors arrive, page views and events appear on the website's dashboard in real time. The tracking script is cookieless and collects no personal data, so no cookie banner is required.

Step 8 - Read your analytics

Select a website from the Websites view to open its dashboard. You see page views and visitors over time, top pages, referrers, countries, browsers, operating systems and devices, plus any custom events you send. Use the date-range selector to change the reporting period, and the Reports section to build funnels, retention, journeys, UTM and other reports.

Where everything lives

Configuration is in /etc/umami/umami.env (the DATABASE_URL and the per-VM APP_SECRET). The application is in /opt/umami and runs from the Next.js standalone build. The PostgreSQL data directory is under /var/lib/postgresql on the dedicated Azure data disk:

findmnt -no SOURCE,SIZE,FSTYPE,TARGET /var/lib/postgresql
ss -tln | grep -E ':80 |:3000 '

Umami is bound to loopback 127.0.0.1:3000 only; the nginx proxy on :80 is the only HTTP entry point.

Application layout and the PostgreSQL data tier on its dedicated data disk

Security baseline

The image is captured from a fully security-patched Ubuntu 24.04 LTS base - including Ubuntu's phased updates, which standard upgrades can silently hold back - and unattended security updates remain enabled on your VM. Confirm the state at any time:

apt-mark showhold
cat /etc/apt/apt.conf.d/20auto-upgrades

No packages are held, and APT::Periodic::Unattended-Upgrade "1" keeps security patches flowing on the running VM.

Fully patched OS security baseline with unattended upgrades enabled

Enabling HTTPS

This image serves HTTP on port 80. For production, terminate TLS in front of Umami. Two common options:

  • Azure-managed TLS: put the VM behind an Azure Application Gateway or Azure Front Door with a managed certificate, and forward to the VM on port 80.
  • On-VM TLS with Let's Encrypt: point a DNS record at the VM's public IP, open port 443 in the NSG, then install certbot and obtain a certificate:
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

certbot edits the nginx site and sets up automatic renewal. After enabling HTTPS, update your tracking script src to use https://.

Service management

Restart Umami after a configuration change with sudo systemctl restart umami. Inspect a service with sudo systemctl status umami (or nginx, postgresql). Umami exposes an unauthenticated heartbeat endpoint, proxied through nginx - a 200 means the application and database are healthy:

curl -s -o /dev/null -w 'heartbeat HTTP %{http_code}\n' http://127.0.0.1/api/heartbeat

Backup and maintenance

  • Database backup: Umami's data is in PostgreSQL. Back it up with pg_dump:

text sudo -u postgres pg_dump umami | gzip > umami-backup-$(date +%F).sql.gz

Restore with psql umami < umami-backup.sql (after gunzip). For point-in-time durability, also snapshot the data disk in Azure. - Resizing storage: the database lives on the dedicated Azure data disk mounted at /var/lib/postgresql. Grow the disk from the Azure portal or CLI, then extend the filesystem on the VM (sudo resize2fs on the data disk device). - OS updates: unattended security updates are enabled; apply everything else with sudo apt-get update followed by sudo apt-get upgrade. Reboot if a new kernel is installed. - Upgrading Umami: back up the database first, then follow the upstream upgrade notes at https://umami.is/docs. Restart the umami service afterwards.

Support

This image is backed by 24/7 cloudimg technical support by email and chat - deployment, adding and tracking websites, building dashboards and reports, database backup and scaling, and TLS termination. Umami is open source software (MIT licensed); cloudimg provides the packaging and support and is not affiliated with or endorsed by the Umami project.

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.