Deployment guide

Umami

Overview

Umami is an open-source, privacy-friendly web analytics platform: a cookieless, self-hosted alternative to Google Analytics. This SecureAnyCloud image runs Umami 2.20 on Ubuntu 24.04 LTS, with a local PostgreSQL 16 database that stores all analytics data.

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. Umami listens on the loopback address 127.0.0.1:3000 and is never exposed directly. nginx runs as a reverse proxy on port 80 and forwards every request to Umami, so 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 oneshot service rotates the administrator password to a fresh per-VM value and generates a fresh APP_SECRET. It 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. Its data directory is 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, so your analytics data never leaves your VM.

What you get:

  • Umami 2.20 built from source at /opt/umami, run as the Next.js standalone server on loopback 127.0.0.1:3000
  • An 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
  • A per-VM administrator password and APP_SECRET, generated at first boot into a root-only file
  • umami.service, nginx.service and postgresql.service as enabled, active systemd units
  • A fully security-patched Ubuntu 24.04 LTS base (phased updates included) at image build time
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2ms (2 vCPU / 8 GiB RAM) is a good starting point. Scale up for higher traffic volumes.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp from your users. For public exposure, put TLS in front of port 80 (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 SecureAnyCloud, and select Create.

On the Basics tab, 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 select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:umami-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name umami \
  --image sac1647283583153:umami-ubuntu-24-04:default:latest \
  --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

Connect to the VM over SSH as the administrator user set in Step 2.

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

The application runs as 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. Check them:

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.

Step 5 - Retrieve your administrator password

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

sudo cat /root/umami-credentials.txt

The file contains the sign-in URL, the username admin and the generated password. Keep the password somewhere safe.

Step 6 - Sign in to Umami

Open http://<vm-public-ip>/ in your browser. The Umami sign-in page opens. Enter the username admin and the password from the credentials file, then sign in.

You land on the Umami dashboard. A fresh VM has no data yet. Add a website in the next step to start collecting analytics.

Once you are signed in, replace the generated per-VM password with your own. 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

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

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

<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 in the Websites view to open its dashboard. The dashboard shows 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. Use the Reports section to build funnels, retention, journeys, UTM and other reports.

Where everything lives

Configuration is in /etc/umami/umami.env, which holds 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.

Security baseline

The image is captured from a fully security-patched Ubuntu 24.04 LTS base. That includes Ubuntu's phased updates, which standard upgrades can silently hold back. 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.

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 you enable HTTPS, update your tracking script src to use https://.

Service management

After a configuration change, restart Umami 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 response 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, for example: sudo -u postgres pg_dump umami | gzip > umami-backup-$(date +%F).sql.gz. To restore, run 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 SecureAnyCloud technical support by email and chat. Support covers deployment, adding and tracking websites, building dashboards and reports, database backup and scaling, and TLS termination.

Umami is open-source software (MIT licensed). SecureAnyCloud 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. Their use does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch Umami on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure