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
:80and the backoffice on:443with 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:5000only 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
/healthzendpoint 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/tcpfrom your management network. - Allow
443/tcpfor the backoffice and the site over HTTPS. - Allow
80/tcpfor 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 StandardThen 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 910Step 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-firstbootss -tlnH 'sport = :5000 or sport = :80 or sport = :443' | awk '{print $4}' | sort -uStep 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.txtSign 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.shStep 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 AspNetCorecurl -sk -o /dev/null -w 'https /healthz -> %{http_code}\n' https://127.0.0.1/healthzfindmnt -no SOURCE,TARGET,FSTYPE,SIZE /var/lib/umbracoAdding 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 umbracoSecurity 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
/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
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
Overview
Umbraco is an open-source content management system built on ASP.NET Core. This image runs Umbraco 17.5.3, the current patch of the Umbraco 17 long-term support release, on the .NET 10 runtime.
The application server (Kestrel) is bound to 127.0.0.1 and is never reachable from the network. nginx is the only network listener. It serves the public website and an unauthenticated health endpoint on port 80, and it serves the back office over HTTPS on port 443.
Content is stored in an embedded SQLite database, so you have no separate database server to license, patch or operate. This suits a single-instance site. If you need a clustered or externally hosted database, Umbraco also supports Microsoft SQL Server, and you can repoint the connection string.
The image ships with no database at all. On the first boot of every instance, a one-shot service creates the database from scratch. It also generates an administrator password, an ASP.NET Core Data Protection key ring and a TLS key that are unique to that instance. Two instances launched from this image never share any of them.
What is in the image
Component Detail
Umbraco CMS 17.5.3 (Umbraco 17 long term support line, MIT licensed)
Runtime .NET 10 / ASP.NET Core 10, installed from the Ubuntu archive
Web server nginx, port 80 (public site) and port 443 (back office)
Application server Kestrel on 127.0.0.1:5000, loopback only
Database SQLite, embedded, on a dedicated data volume
Health endpoint http://<public-ip>/healthz, unauthenticated, served by nginx
Prerequisites
Before you deploy this image, make sure you have:
- An AWS account with permission to launch EC2 instances.
- A security group that allows inbound TCP 22 from your administration address, and TCP 80 and 443 from wherever your site's visitors and editors will connect.
- An EC2 key pair, so that you can read the generated administrator password over SSH.
- An instance type of at least
m5.large. Umbraco compiles Razor views and builds its cache on the first request, so smaller burstable types make the first page load noticeably slower.
Connecting to your instance
OS variant SSH login user Command
Ubuntu 24.04 ubuntu ssh -i /path/to/key.pem ubuntu@<public-ip>
The ubuntu user has passwordless sudo. The image has no other login account, and no account has a password.
First boot
First boot takes roughly two to three minutes. During that time the instance does the following:
- Reads its own public IPv4 address from EC2 IMDSv2, so that the back office sign-in flow is registered against the address you will browse to.
- Generates a random administrator password.
- Creates the SQLite database and the administrator account.
- Generates a fresh ASP.NET Core Data Protection key ring, which signs and encrypts the back office authentication cookie.
- Generates a self-signed TLS certificate and key for the HTTPS listener.
- Starts nginx and writes the credentials file.
Check that both services are up:
systemctl is-active umbraco.service nginx.serviceConfirm the runtime version:
dotnet --list-runtimesConfirm that the health endpoint answers. This endpoint needs no credential, so you can point a load balancer health check at it:
curl -s http://127.0.0.1/healthzRetrieving your administrator password
The credentials file has mode 0600, so only root can read it. List its keys:
sudo grep -oE '^[A-Z_]+=' /root/umbraco-credentials.txtTo read the password itself, run one of the commands below on your instance. This guide deliberately does not reproduce the password, because the value is unique to your instance:
What you want Command to run on the instance
The whole credentials file sudo cat /root/umbraco-credentials.txt
Just the administrator email sudo grep '^UMBRACO_ADMIN_USER=' /root/umbraco-credentials.txt \| cut -d= -f2-
Just the password sudo grep '^UMBRACO_ADMIN_PASSWORD=' /root/umbraco-credentials.txt \| cut -d= -f2-
Signing in to the back office
Open https://<public-ip>/umbraco in a browser and sign in with the email address and password from the credentials file.
Keep two things in mind:
- The back office is HTTPS only, and that is deliberate. Umbraco 17's back office is a single-page application whose sign-in uses
window.crypto.subtle, which browsers expose only in a secure context. Over plain HTTP the sign-in cannot complete. Port 80 therefore redirects/umbracoto HTTPS and serves the public website. - Your browser warns about the certificate once. The image generates a self-signed certificate for each instance rather than shipping a shared one. Accept the warning to sign in. Then replace the certificate as described below before you put the site in front of the public.
The public website is served at http://<public-ip>/. Until you publish your first page, it shows Umbraco's "Welcome to your Umbraco installation" holding page.
Verifying the sign-in works and a wrong password is rejected
The image ships a self-check that exercises the real sign-in path through nginx on port 443. It proves that your instance's password is accepted, and that a wrong password is rejected with an explicit HTTP 401 rather than merely failing to succeed. The check prints no secret:
sudo /usr/local/sbin/umbraco-cred-roundtrip.shConfirming this instance's secrets are its own
Every piece of secret material is generated per instance. This command prints SHA-256 digests of that material, never the material itself, so that you can compare two instances and confirm that they differ:
sudo /usr/local/sbin/umbraco-instance-fingerprint.shRun it on two instances launched from the same image, and all four digests differ. The Data Protection key ring matters most. It is the key that signs the back office authentication cookie, so if two instances shared it, one instance would accept a cookie minted on the other.
Storage layout
Two dedicated EBS volumes are attached and mounted, separate from the operating system disk. Check them:
df -h --output=source,size,used,avail,target /var/lib/umbraco /var/lib/umbraco-mediaBoth volumes are recorded in /etc/fstab by filesystem UUID, so the layout reproduces on every instance launched from this image:
grep umbraco /etc/fstabPath Holds
/var/lib/umbraco SQLite content database, ASP.NET Data Protection key ring, Umbraco runtime cache and logs
/var/lib/umbraco-media The media library: every image, document and asset uploaded through the back office
/opt/umbraco/app The published application, on the OS disk, root owned and read only to the service account
Media is on its own volume because it is the tier that grows without bound on a content-managed site. You can grow either volume, without touching the other, by modifying the EBS volume and then running sudo resize2fs <device>.
Network exposure
The application server is bound to loopback and is not reachable from outside the instance. Only nginx listens on a routable address. Verify this:
sudo ss -tlnp | grep -E 'dotnet|nginx'dotnet appears only on 127.0.0.1:5000. If you ever see it on 0.0.0.0, something has changed the ASPNETCORE_URLS setting in /var/lib/umbraco/umbraco.env. Restore the original value.
Replacing the self-signed certificate
For production, replace the generated certificate with one for your own domain. The simplest approach on AWS is to terminate TLS at an Application Load Balancer, using an AWS Certificate Manager certificate, and forward to the instance.
To install a certificate directly on the instance instead, place your certificate and key at /etc/nginx/ssl/umbraco.crt and /etc/nginx/ssl/umbraco.key (key mode 0600). Then run sudo nginx -t && sudo systemctl reload nginx.
If you move the site to a custom domain, also update Umbraco__CMS__WebRouting__UmbracoApplicationUrl in /var/lib/umbraco/umbraco.env to that domain, and restart umbraco.service. That value seeds the permitted redirect addresses for the back office sign-in flow, so sign-in fails on a host that the value does not cover.
Licensing
Umbraco CMS is open-source software under the MIT license. The image includes the upstream license text:
head -3 /usr/local/share/sac-umbraco/LICENSE.mdTo see the exact Umbraco version that this image resolved and published, run:
python3 -c "import json;d=json.load(open('/opt/umbraco/app/Sac.Umbraco.deps.json'));print(sorted(k for k in d['libraries'] if k.startswith('Umbraco.Cms/'))[0])"This image contains only the MIT-licensed Umbraco CMS. Umbraco Cloud and Umbraco's commercial add-on products are not included. SecureAnyCloud is not affiliated with, endorsed by or sponsored by Umbraco HQ. This guide uses the Umbraco name only to identify the open-source software that the image includes.
Your SecureAnyCloud charges are for the packaging, hardening and support around the software, not for the software itself.
Backup and maintenance
- Backup. The content database and the media library both live on the two data volumes, so an AWS Backup plan or scheduled EBS snapshots of those volumes capture the whole site. Snapshot both volumes together for a consistent restore.
- Operating system updates.
unattended-upgradesis enabled. The .NET runtime is installed from the Ubuntu archive rather than a third-party feed, so ASP.NET Core security updates arrive on the same stream as the rest of the operating system. - Umbraco upgrades. Umbraco 17 is a long-term support release supported until 27 November 2028. Take a snapshot of both data volumes before any upgrade.
- Logs. Application logs are under
/var/lib/umbraco/umbraco-runtime/Logs. Service logs are in the journal:sudo journalctl -u umbraco.service.
Screenshots
The Umbraco back office sign-in page:
The Settings section, where you model document types, templates and data types:
The public website immediately after launch, before you publish any content:
The media library, stored on its own dedicated volume:
Support
SecureAnyCloud provides 24/7 technical support by email and live chat for this image. Support covers launch, configuration, upgrades and operational questions. We aim to respond within one business day.
- Email: sales@secureanycloud.com
- Web: secureanycloud.com
Deploy on AWS
Launch Umbraco CMS on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com