Umbraco on Ubuntu 24.04 on Azure User Guide
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
:80and the backoffice on:443with 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:5000only, 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
/healthzendpoint 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

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

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.

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.

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.

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.

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

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

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
/umbracoare redirected to HTTPS. - Kestrel listens on
127.0.0.1:5000only 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.txtprotected 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/tcpand443/tcpin 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.