Um
Applications Azure

Umbraco on Ubuntu 24.04 on Azure User Guide

| Product: Umbraco on Ubuntu 24.04 LTS on Azure

Overview

Umbraco is a flexible, friendly open source content management system built on ASP.NET Core and .NET. It gives content editors a clean, modern backoffice for building pages, document types, templates and media, and gives developers a full Model, View, Controller and API surface for building sites and applications. The cloudimg image ships Umbraco 17.5.3 on the .NET 10 runtime, running as an ASP.NET Core application under Kestrel behind nginx on a hardened, fully patched Ubuntu 24.04 LTS base. The appliance is self contained: it uses an embedded SQLite database, so there is no separate database server to run. A unique administrator account is created on the first boot of every VM using a per VM secret, and the backoffice is served over HTTPS so its browser login works out of the box. Backed by 24/7 cloudimg support.

What is included:

  • Umbraco 17.5.3 (MIT licensed) on the .NET 10 runtime, run by Kestrel under systemd as umbraco.service
  • An embedded SQLite database, so the appliance is complete on its own with no external database server
  • nginx serving the public website on :80 and the backoffice on :443 with a per VM self signed TLS certificate
  • A per VM administrator account created on first boot and recorded in a root only credentials file
  • No shipped default login: the first admin is created with a unique per VM secret, and no known or blank credential authenticates
  • Kestrel bound to 127.0.0.1:5000 only, never exposed to the network; nginx is the only public listener
  • A dedicated Azure data disk holding the SQLite database, the media library and the ASP.NET Core DataProtection keyring
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 cloudimg support

This image ships only the open source, MIT licensed Umbraco CMS. It is not affiliated with or endorsed by Umbraco. Umbraco Cloud and paid add ons are separate products and are not included.

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; size up for larger or busier sites. NSG inbound: allow 22/tcp from your management network, 443/tcp for the backoffice and the site over HTTPS, and 80/tcp for the public site over HTTP. The embedded SQLite database is never exposed on the network, and Kestrel listens on 127.0.0.1 only.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Umbraco 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), HTTP (80) and HTTPS (443). Review the dedicated data disk on the Disks tab, then Review + create then Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name umbraco \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Then open ports 80 and 443:

az vm open-port --resource-group <your-rg> --name umbraco --port 80 --priority 900
az vm open-port --resource-group <your-rg> --name umbraco --port 443 --priority 910

Step 3 - Confirm the services are running

SSH in as azureuser and confirm the Umbraco (Kestrel) service, nginx and the first boot unit are all active. Kestrel listens only on 127.0.0.1:5000; nginx is the only public listener, serving :80 and :443.

systemctl is-active umbraco nginx umbraco-firstboot
ss -tlnH 'sport = :5000 or sport = :80 or sport = :443' | awk '{print $4}' | sort -u

The umbraco, nginx and umbraco-firstboot services active, with Kestrel bound to loopback 127.0.0.1:5000 and nginx listening on ports 80 and 443

Step 4 - Retrieve the per VM administrator login

Every VM creates its own Umbraco administrator on first boot and writes the login email, the generated password and the URLs to a root only credentials file. Read it with sudo:

sudo cat /root/umbraco-credentials.txt

The per VM Umbraco credentials file, showing the admin login email, the generated password and the backoffice and site URLs

You sign in to the backoffice with the UMBRACO_ADMIN_USER email and the UMBRACO_ADMIN_PASSWORD from this file.

Step 5 - Sign in to the backoffice

Browse to https://<vm-public-ip>/umbraco. Because the VM ships a per VM self signed certificate, your browser shows a one time certificate warning the first time; accept it to continue (replace the certificate with your own for production, see below). The backoffice is served over HTTPS on purpose: its modern login uses browser cryptography that only works in a secure context. Sign in with the email and password from Step 4.

The Umbraco backoffice login page served over HTTPS, with the Umbraco welcome panel and the e mail and password fields

Step 6 - The Content section

After signing in you land in the Content section. This is where you build and publish the pages of your site. The left tree holds your content nodes and the Recycle Bin, and the dashboard gives you a starting point and links into the documentation. Use the Create action on the Content root to add your first page once you have defined a document type.

The Umbraco backoffice Content section showing the content tree, the Recycle Bin and the Welcome to Umbraco dashboard

Step 7 - The Settings section

Open the Settings section from the top navigation to define the building blocks of your site: Document Types (the content models), Templates, Partial Views, Stylesheets, Scripts, Media Types, Data Types and Languages. This is where developers and editors shape how content is structured and rendered.

The Umbraco backoffice Settings section showing Document Types, Templates, Partial Views, Stylesheets and the other structure and templating folders

Step 8 - The public website

Your public site is served on http://<vm-public-ip>/ and https://<vm-public-ip>/. On a fresh install, before you publish any content, Umbraco serves its friendly starter page confirming the installation is running. As soon as you create and publish a home page in the Content section, that page replaces this one at the site root.

The rendered public Umbraco starter site showing the Welcome to your Umbraco installation page and the Open Umbraco call to action

Step 9 - No known or default credentials

Umbraco ships no default login. The cloudimg image goes further: the captured image contains no database at all, and the administrator account is created with a unique per VM secret the first time the VM boots. You can prove that only the per VM secret works with the built in round trip check, which confirms the per VM administrator signs in through the backoffice login API while a blank password, common guesses and any build time value are all rejected:

sqlite3 /var/lib/umbraco/data/Umbraco.sqlite.db "SELECT userLogin FROM umbracoUser WHERE userLogin='admin@cloudimg.local'"
sudo bash /usr/local/sbin/umbraco-cred-roundtrip.sh

The Umbraco admin account present in the umbracoUser table, and the round trip check confirming the per VM admin authenticates while blank, known and build time guesses are rejected and the account is not locked

Step 10 - Verify the stack and where your data lives

Confirm the ASP.NET Core runtime, the health endpoint, the dedicated data disk and the database. The SQLite database, the media library and the ASP.NET Core DataProtection keyring all live on the data disk mounted at /var/lib/umbraco, so all of your site's content is kept separate from the operating system disk and rides with the VM. Persisting the DataProtection keyring on disk is what keeps you signed in to the backoffice across service restarts.

dotnet --list-runtimes | grep AspNetCore
curl -sk -o /dev/null -w 'https /healthz -> %{http_code}\n' https://127.0.0.1/healthz
findmnt -no SOURCE,TARGET,FSTYPE,SIZE /var/lib/umbraco

The ASP.NET Core 10 runtime present, the https healthz endpoint returning 200, the ext4 data disk mounted at /var/lib/umbraco and the SQLite database with its backoffice user count

Adding your own domain and TLS

The image ships a per VM self signed certificate so the backoffice works immediately over HTTPS. For production, front the site with your own domain and a trusted TLS certificate. Replace the certificate and key in /etc/nginx/ssl/ with your own (or terminate TLS at Azure Application Gateway or a load balancer), and set your public address so Umbraco generates correct links and the backoffice login accepts your host. Edit the Umbraco__CMS__WebRouting__UmbracoApplicationUrl value in /var/lib/umbraco/umbraco.env to your https://your-domain, then restart:

sudo systemctl restart umbraco

Security notes

  • The backoffice is served over HTTPS with a per VM self signed certificate; replace it with a certificate for your own domain for production. HTTP requests to /umbraco are redirected to HTTPS.
  • Kestrel listens on 127.0.0.1:5000 only and is never reachable from the network. nginx is the only public listener.
  • The administrator account is unique per VM and no known or blank credential authenticates. Keep /root/umbraco-credentials.txt protected and change the password from within the backoffice if you share access.
  • The SQLite database, media and DataProtection keyring live on the dedicated data disk at /var/lib/umbraco.
  • Restrict inbound 80/tcp and 443/tcp in your NSG to the networks that need the site and the backoffice.

Support

This image is maintained by cloudimg with 24/7 support. If you need help deploying or operating Umbraco on Azure, contact us at cloudimg.co.uk.