Operating Systems Azure

Ubuntu Server 26.04 LTS on Azure User Guide

| Product: Ubuntu Server 26.04 LTS on Azure

Overview

This guide covers the deployment, verification and day one operation of Ubuntu Server 26.04 LTS (Resolute Raccoon) on Microsoft Azure, using the cloudimg virtual machine image from the Azure Marketplace.

Ubuntu Server 26.04 LTS is the current long term support release of Ubuntu. Canonical released it on 23 April 2026 and provides five years of standard security maintenance for it, to April 2031. Because it is a long term support release, its kernel, toolchain and library surface stay stable for years, so software you build against it keeps working without a distribution upgrade partway through a project.

What is included:

  • Ubuntu Server 26.04 LTS, fully patched at the moment the image was captured
  • Security updates applied with phased updates included, so nothing was quietly held back
  • Unattended security upgrades enabled, so the instance keeps patching itself
  • Azure Linux Agent (walinuxagent) and cloud init for full Azure platform integration
  • AppArmor mandatory access control enabled
  • No baked password, no bundled SSH key and no swap on the operating system disk
  • Generation 2 Hyper V virtual machine support
  • 24/7 cloudimg support

Platform: Microsoft Azure (Generation 2 Hyper V) Default user: azureuser Recommended size: Standard_B2s (2 vCPU, 4 GB RAM) or larger

Prerequisites

Before deploying this image, ensure you have:

  1. An active Microsoft Azure subscription
  2. Access to the Azure Portal or the Azure CLI
  3. An SSH key pair for Linux virtual machine access
  4. Familiarity with Azure virtual machine management

Step 1: Deploy the virtual machine

Option A: Azure Portal

  1. Open the Azure Marketplace and search for "Ubuntu Server 26.04 LTS cloudimg"
  2. Select the image and click Create
  3. Configure the basics:
  4. Subscription: your Azure subscription
  5. Resource group: create a new one or select an existing one
  6. Virtual machine name: a name of your choosing
  7. Region: your preferred Azure region
  8. Size: Standard_B2s or larger
  9. Under Administrator account, choose SSH public key and paste your public key. The user name is azureuser
  10. Under Inbound port rules, allow SSH (port 22) from your own address range rather than from the whole internet
  11. Click Review + create, then Create

Option B: Azure CLI

az vm create \
  --resource-group myResourceGroup \
  --name my-ubuntu-2604-vm \
  --image cloudimg:ubuntu-server-26-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

The image ships no password and no authorized key of its own. The only credential that will ever work is the SSH public key you supply here, which Azure injects at provisioning time.

Step 2: Connect over SSH

ssh azureuser@<vm-ip>

To find the public address of your virtual machine:

az vm show --subscription <sub-id> --resource-group myResourceGroup \
  --name my-ubuntu-2604-vm --show-details --query publicIps -o tsv

Step 3: Confirm which release you are running

Confirm the release, the kernel and that the Azure platform integration is healthy.

cat /etc/os-release

Expected output:

PRETTY_NAME="Ubuntu 26.04 LTS"
NAME="Ubuntu"
VERSION_ID="26.04"
VERSION="26.04 LTS (Resolute Raccoon)"
VERSION_CODENAME=resolute
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=resolute
LOGO=ubuntu-logo
uname -r
uname -m
hostnamectl | grep -E "Operating System|Kernel|Virtualization|Architecture"

Expected output:

7.0.0-1010-azure
x86_64
   Virtualization: microsoft
 Operating System: Ubuntu 26.04 LTS
           Kernel: Linux 7.0.0-1010-azure
     Architecture: x86-64

The -azure kernel flavour is the Azure tuned kernel that Canonical maintains for this platform. Confirm the Azure Linux Agent and cloud init are present:

systemctl is-active walinuxagent.service
systemctl is-enabled walinuxagent.service
cloud-init --version

Expected output:

active
enabled
/usr/bin/cloud-init 26.1-0ubuntu2

Terminal showing cat /etc/os-release reporting Ubuntu 26.04 LTS Resolute Raccoon, the 7.0.0-1010-azure kernel, x86_64 architecture and the Azure Linux Agent reporting active and enabled

Step 4: Confirm the image is fully patched

Ubuntu rolls a proportion of its updates out in phases, so a plain apt-get upgrade can report success while a subset of updates, including security updates, is still being held back on that particular machine. cloudimg patches this image with phased updates explicitly included, and you can verify that for yourself.

First check that nothing is pinned to an old version:

sudo apt-get update -qq
apt-mark showhold

The apt-mark showhold command prints nothing, because no package is held. A held package would silently block its own security updates forever.

Now simulate an upgrade with phased updates included and count what is left:

sudo apt-get -s -o APT::Get::Always-Include-Phased-Updates=true dist-upgrade | grep -c "^Inst " || true

Expected output on a freshly deployed instance:

0

Zero means the image genuinely has every available update applied, not merely the ones your machine happened to be offered. If you run this some weeks after deployment the number will be higher, which simply means Ubuntu has published updates since the image was captured. Apply them with sudo apt-get update && sudo apt-get -o APT::Get::Always-Include-Phased-Updates=true dist-upgrade.

Terminal showing a simulated dist upgrade with phased updates included, reporting no held packages, zero packages upgradable, the resolute security pocket enabled and the periodic unattended upgrade settings

Step 5: Review the secure by default posture

Nothing known ships inside this image. There is no default password, no bundled SSH key and no shared host key. Confirm it.

sudo passwd -S root | awk '{print $1, $2}'
sudo sshd -T | grep -E "^(permitrootlogin|passwordauthentication|pubkeyauthentication)"

Expected output:

root L
permitrootlogin prohibit-password
pubkeyauthentication yes
passwordauthentication no

L means the root account is locked, so there is no root password to guess. passwordauthentication no means SSH will not accept a password from anyone, so the key you supplied at deployment is the only way in. The SSH host keys and the machine identifier are regenerated uniquely on the first boot of every instance, so no two deployments share them.

AppArmor, the mandatory access control system Ubuntu uses to confine services, is enabled:

sudo aa-status --enabled && echo "apparmor: enabled"
sudo aa-status --profiled

Expected output:

apparmor: enabled
177

Terminal showing the root account locked, password authentication disabled, public key authentication enabled and AppArmor enabled with 177 profiles loaded

Step 6: Check resources and install your software

df -h /
free -h
systemctl is-system-running
systemctl list-units --state=failed --no-legend | wc -l

Expected output on a Standard_B2s instance:

Filesystem      Size  Used Avail Use% Mounted on
/dev/root        28G  2.2G   26G   8% /

               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       532Mi       2.9Gi       4.0Mi       614Mi       3.3Gi
Swap:             0B          0B          0B

running
0

running with zero failed units means the system reached its target state cleanly. Swap: 0B is deliberate: Azure manages swap on the ephemeral resource disk through the Azure Linux Agent rather than on the operating system disk, so no swap is baked into the image.

The complete Ubuntu archive is available, so any package you need is one command away:

apt-cache policy nginx

Expected output:

nginx:
  Installed: (none)
  Candidate: 1.28.3-2ubuntu1.8

Install what you need in the usual way, for example sudo apt-get install -y nginx.

Terminal showing 28 GB of root disk with 26 GB available, 3.8 GB of memory with no swap, systemd running with zero failed units, and the nginx package available from the archive

Step 7: Automatic security updates

The image keeps Ubuntu's unattended upgrades mechanism enabled, so security updates are applied without you having to log in. Confirm the configuration:

cat /etc/apt/apt.conf.d/20auto-upgrades

Expected output:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

And confirm the service unit itself is enabled:

systemctl show -p UnitFileState --value unattended-upgrades.service

Expected output:

enabled

To see what it has been doing:

sudo tail -n 20 /var/log/unattended-upgrades/unattended-upgrades.log 2>/dev/null || echo "no upgrade run recorded yet on this instance"

If you prefer to control patching yourself, disable it with sudo systemctl disable --now unattended-upgrades.service. Bear in mind that you then own the patching schedule.

Step 8: Restrict SSH access

Your Azure Network Security Group is the first line of defence and should already limit port 22 to your own address range. If you also want a host firewall, enable it in this order so that you never lock yourself out. Allow SSH first, then enable the firewall.

sudo ufw allow from <your-mgmt-cidr> to any port 22 proto tcp
sudo ufw --force enable
sudo ufw status verbose

Replace the placeholder with the address range you administer the instance from. The image ships with the host firewall inactive so that it never interferes with your own network design.

Step 9: Set the time zone and host name

The instance runs in UTC with time synchronisation active, which is the right default for servers.

timedatectl | head -6

Expected output:

               Local time: Sat 2026-07-25 17:42:38 UTC
           Universal time: Sat 2026-07-25 17:42:38 UTC
                 RTC time: Sat 2026-07-25 17:42:37
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active

To change the time zone or the host name:

sudo timedatectl set-timezone Europe/London
sudo hostnamectl set-hostname web01.<your-domain>

Troubleshooting

SSH refuses the connection. Password authentication is disabled by design. Connect with the private key that matches the public key you supplied at deployment, and confirm the Network Security Group allows port 22 from your address.

A package fails to install. Refresh the package lists first with sudo apt-get update. The image ships with the archive metadata cleared so that every instance fetches a current index.

Updates appear after deployment. That is expected and healthy. The image was fully patched at capture, and Ubuntu has published updates since. Unattended upgrades will apply security updates automatically, or you can apply everything immediately with a dist upgrade that includes phased updates.

Support

This image is supported 24/7 by cloudimg. Contact support@cloudimg.co.uk with your subscription identifier and the virtual machine name.

Ubuntu is a trademark of Canonical Ltd. cloudimg is not affiliated with or endorsed by Canonical Ltd. Ubuntu is free and open source software; running Ubuntu Server requires no licence key and no paid subscription.