Deployment guide

Umbraco

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. It gives developers a full Model, View, Controller and API surface for building sites and applications.

The SecureAnyCloud image ships Umbraco 17.5.3 on the .NET 10 runtime. It runs as an ASP.NET Core application under Kestrel, behind nginx, on a hardened Ubuntu 24.04 LTS base that is patched at build time. The appliance is self-contained. It uses an embedded SQLite database, so you have no separate database server to run.

What you get:

  • 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, so the browser login works out of the box
  • 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 and never exposed to the network, so 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 SecureAnyCloud 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

Before you deploy this image, make sure you have:

  • An active Azure subscription
  • An SSH key pair
  • A VNet and subnet in the target region
  • A VM size of Standard_B2s (2 vCPU / 4 GiB RAM) or larger. This size is a sensible starting point, and you can size up for larger or busier sites.

Configure the NSG inbound rules as follows:

  • Allow 22/tcp from your management network.
  • Allow 443/tcp for the backoffice and the site over HTTPS.
  • Allow 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 and choose Create a resource. Search the Marketplace for Umbraco by SecureAnyCloud, 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).
  • On the Disks tab, review the dedicated data disk.
  • Choose Review + create, and then choose Create.

Step 2 - Deploy from the Azure CLI

Accept the Marketplace terms and create the VM:

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:umbraco-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name umbraco \
  --image sac1647283583153:umbraco-ubuntu-24-04:default:latest \
  --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 that 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, and it serves :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. It writes the login email, the generated password and the URLs to a root-only credentials file. Read the file with sudo:

sudo cat /root/umbraco-credentials.txt

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. The VM ships a per-VM self-signed certificate, so your browser shows a one-time certificate warning the first time. Accept the warning to continue, and replace the certificate with your own for production (see "Adding your own domain and TLS" below).

The backoffice is served over HTTPS on purpose, because its modern login uses browser cryptography that works only in a secure context. Sign in with the email and password from Step 4.

Step 6 - The Content section

After you sign in, you land in the Content section, where you build and publish the pages of your site. The left tree holds your content nodes and the Recycle Bin. The dashboard gives you a starting point and links into the documentation.

Once you have defined a document type, use the Create action on the Content root to add your first page.

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. Developers and editors use this section to 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 starter page to confirm that the installation is running. When you create and publish a home page in the Content section, that page replaces the starter page at the site root.

Step 9 - No known or default credentials

Umbraco ships no default login. The SecureAnyCloud image goes further: the captured image contains no database at all, and the first boot of each VM creates the administrator account with a unique per-VM secret.

You can prove that only the per-VM secret works by using the built-in round-trip check. The check confirms that 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@sac.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. All of your site's content is therefore separate from the operating system disk and moves with the VM. Persisting the DataProtection keyring on disk 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 that 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. Then set your public address so that 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, and then restart the service:

sudo systemctl restart umbraco

Security notes

  • The backoffice is served over HTTPS with a per-VM self-signed certificate. For production, replace it with a certificate for your own domain. 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

SecureAnyCloud maintains this image and provides 24/7 support. If you need help deploying or operating Umbraco on Azure, contact us at secureanycloud.com.

Deploy on Azure

Launch Umbraco 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