Operating Systems Azure

Azure Linux 3.0 on Azure User Guide

| Product: Azure Linux 3.0 on Azure

Overview

This guide covers the deployment and configuration of Microsoft Azure Linux 3.0 on Microsoft Azure using cloudimg's pre configured virtual machine image from the Azure Marketplace.

Azure Linux, formerly CBL Mariner, is Microsoft's own open source Linux distribution. It is developed in the open at github.com/microsoft/azurelinux and is used as a container host and cloud platform across Microsoft's own services. It is deliberately small: a lean, security focused package set that keeps the attack surface and footprint low, with fast, signed updates from Microsoft's own repositories. Its native package manager is tdnf (Tiny DNF), an RPM based, dnf compatible resolver; the full dnf tool is also present.

What's included:

  • Microsoft Azure Linux 3.0, x86_64, Gen2 Hyper V
  • Every available update applied at build time from the official Azure Linux repositories
  • dnf-automatic armed, so the machine keeps applying updates on its own
  • Azure Linux Agent (waagent) and cloud-init for Azure integration
  • Chronyd for NTP time synchronisation
  • Key only SSH: root password locked, password authentication disabled
  • Signed update path from all four official Azure Linux repositories
  • 24/7 cloudimg support

Platform: Microsoft Azure (Gen2 Hyper V) Default user: azureuser

Security posture

This image ships with no known credential. There is no default password and no baked in SSH key:

  • The root account password is locked, so no one can log in as root with a password.
  • PasswordAuthentication is disabled in the SSH daemon, so every login is by key.
  • PermitRootLogin is set to prohibit-password (reported by OpenSSH as without-password), so root cannot be reached with a password even if one were later set.
  • The only key that works is the public key you supply when you create the virtual machine. Azure injects it into azureuser at first boot, so no two machines you launch ever share a secret.
  • The machine identity and the SSH host keys are regenerated uniquely on every instance, so no two machines share a host key either.
  • Azure Linux does not ship SELinux. It is a minimal, cloud and container host distribution, and its security model relies on the small footprint, the signed update path, key only SSH and the Azure Network Security Group rather than a mandatory access control layer.

Prerequisites

Before deploying this image, ensure you have:

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

Recommended VM Size: Standard_B2s (2 vCPU, 4 GB RAM) or larger.

Step 1: Deploy the Virtual Machine

Option A: Azure Portal

  1. Navigate to the Azure Marketplace and search for "Azure Linux 3.0 cloudimg"
  2. Select the image and click Create
  3. Configure the basics:
  4. Subscription: Select your Azure subscription
  5. Resource Group: Create new or select existing
  6. Virtual Machine Name: Enter a name for your VM
  7. Region: Select your preferred Azure region
  8. Size: Standard_B2s recommended
  9. Under Administrator Account, select SSH public key and enter your key
  10. Under Inbound Port Rules, allow SSH (port 22)
  11. Click Review + Create, then Create

Option B: Azure CLI

az vm create \
  --resource-group myResourceGroup \
  --name my-azure-linux-3-vm \
  --image cloudimg:azure-linux:azl3:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Step 2: Connect via SSH

Run these on your own workstation, not on the VM. Find the public IP, then connect:

az vm show --resource-group myResourceGroup --name my-azure-linux-3-vm --show-details --query publicIps -o tsv
ssh azureuser@<vm-ip>

There is no password to enter. If SSH asks you for one, the key you supplied at create time is not the key your client is offering.

Step 3: Confirm the release

Check that the machine is the Azure Linux 3.0 release you expect:

cat /etc/azurelinux-release
grep -E '^(NAME|VERSION|ID|VERSION_ID|PRETTY_NAME)=' /etc/os-release
tdnf --version
uname -srm

Expected output:

Azure Linux release 3.0
NAME="Microsoft Azure Linux"
VERSION="3.0.20260712"
ID=azurelinux
VERSION_ID="3.0"
PRETTY_NAME="Microsoft Azure Linux 3.0"
tdnf: 3.5.8
Linux 6.6.144.1-1.azl3 x86_64

The terminal shows cat of etc azurelinux-release reporting Azure Linux release 3.0, the os-release fields NAME Microsoft Azure Linux, VERSION 3.0, ID azurelinux and PRETTY_NAME Microsoft Azure Linux 3.0, the tdnf version, and uname reporting the 6.6 azl3 kernel on x86_64

The azl3 tag on the kernel version is the marker that this machine is Azure Linux 3.x. The ID field is azurelinux; the earlier CBL Mariner 2 series reports ID=mariner and VERSION_ID=2.0 instead.

Step 4: Check the patch level

The image is fully updated at build time. tdnf is the native package manager, but for a machine readable patched check the dnf tool that ships alongside it follows the standard convention: it returns exit code 100 when updates are pending and 0 when none are:

sudo dnf -q check-update; echo "exit code: $?"

List the enabled repositories to confirm your update path is intact:

tdnf repolist

Expected output:

exit code: 0
repo id                          repo name                                       status
azurelinux-official-cloud-native Azure Linux Official Cloud Native 3.0 x86_64    enabled
azurelinux-official-ms-oss       Azure Linux Official Microsoft Open-Source ...  enabled
azurelinux-official-base         Azure Linux Official Base 3.0 x86_64            enabled
azurelinux-official-ms-non-oss   Azure Linux Official Microsoft Non-Open-Sou...  enabled

The terminal shows dnf check-update returning exit code 0 meaning no updates are pending, tdnf repolist listing the four official Azure Linux repositories as enabled, dnf-automatic.timer reported as enabled, the automatic.conf apply_updates and download_updates set to yes, and the running azl3 kernel version

This image arms dnf-automatic, so updates are downloaded and applied on a timer without any action from you. You can still update on your own schedule with the native tools:

sudo tdnf -y update

Reboot if a new kernel was installed:

sudo systemctl reboot

Step 5: Verify the security posture

Confirm root is locked, no account ships a usable password, and SSH is key only:

sudo passwd -S root
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|pubkeyauthentication)'
swapon --show

Expected output:

root L 2026-07-06 7 99999 7 -1
permitrootlogin without-password
pubkeyauthentication yes
passwordauthentication no

The terminal shows passwd -S root reporting the root account as L meaning locked, a check of etc shadow finding no account with a usable password, the effective sshd policy reporting permitrootlogin without-password, pubkeyauthentication yes and passwordauthentication no, and swapon showing no swap in the image

without-password is how OpenSSH reports the prohibit-password setting. Both names mean the same thing: root may not authenticate with a password. swapon --show prints nothing because the image ships with no swap; Azure manages swap on the ephemeral resource disk through waagent if you enable it.

Step 6: Verify Azure integration and unattended updates

Confirm the Azure Linux Agent, cloud-init and time synchronisation are healthy, that unattended updates are armed, and check your resources:

systemctl is-active waagent
systemctl is-enabled waagent
cloud-init --version
systemctl is-enabled dnf-automatic.timer
systemctl is-active chronyd
df -h /
free -h

Expected output:

active
enabled
/usr/bin/cloud-init 24.3.1-3.azl3
enabled
active

The terminal shows waagent active and enabled at boot, cloud-init version 24.3.1 for azl3, dnf-automatic.timer enabled so updates apply on a timer, chronyd active for time synchronisation, the root filesystem usage from df, and the memory summary from free showing no swap

waagent is what lets Azure provision your SSH key, resize the OS disk, run extensions and report VM health, so it should always be active and enabled. dnf-automatic.timer being enabled is what keeps the machine applying updates on its own after launch.

Step 7: Networking and the firewall

The Azure Network Security Group is the control plane for inbound and outbound traffic, and it is the first and usually the only place you need to open a port. The image advertises a single inbound port, SSH on 22.

Azure Linux does not ship or enable a host firewall daemon such as firewalld by default; iptables is present should you wish to add host level rules, but out of the box your NSG rules take effect exactly as written, with no second layer to keep in sync. Confirm what is listening before you open anything:

ss -tlnp

On a fresh machine the external listener is sshd on port 22. You will also see systemd-resolved bound to the loopback addresses 127.0.0.53 and 127.0.0.54 on port 53, which is the local DNS stub resolver and is not reachable from outside. Only port 22 is advertised for inbound access, and the Azure NSG is what governs what is actually reachable.

Step 8: Install software

Azure Linux's package manager is tdnf. Search for a package to confirm it is available:

tdnf list nginx

Then install it and enable it in the usual way, for example sudo tdnf install -y nginx followed by sudo systemctl enable --now nginx. tdnf reads the same four official Azure Linux repositories shown in Step 4. Package names and the install / remove / update verbs mirror dnf, so most familiar workflows carry over directly.

To add another administrator, create the account with sudo useradd -m -G wheel <name>, then copy your public key into /home/<name>/.ssh/authorized_keys with mode 600 and the .ssh directory mode 700, owned by that user. The image ships with no human accounts at all, so azureuser is the only login until you add one:

getent group wheel

Common Use Cases

  • A lean, security focused host for containers and microservices
  • A small footprint cloud base for your own services and stacks
  • A Microsoft aligned Linux platform for Azure native workloads
  • Container image base layers built on Microsoft's own distribution

Troubleshooting

Cannot connect via SSH

  1. Verify the VM is in Running state in the Azure Portal
  2. Check that port 22 is allowed in the Network Security Group
  3. Ensure you are using the correct username: azureuser
  4. Verify your SSH key matches the one you supplied at create time. Password login is disabled by design, so a wrong key cannot fall back to a password prompt.

To see which key your client is actually offering, run ssh -v azureuser@<vm-ip> from your workstation and look for the Offering public key lines.

Azure agent not running

sudo systemctl status waagent
sudo systemctl enable --now waagent

Package manager issues

Refresh the metadata cache first:

sudo tdnf clean all
sudo tdnf makecache

If repositories are unreachable, check DNS resolution. getent is always present and resolves through the same system resolver:

getent hosts packages.microsoft.com

Confirming unattended updates are working

dnf-automatic runs on a systemd timer. Check when it last ran and when it will run next:

systemctl status dnf-automatic.timer
journalctl -u dnf-automatic.service --no-pager | tail -20

Important Notes

Azure Linux is free and open source. Microsoft's own components and the distribution tooling are MIT licensed. As a full Linux distribution it is assembled from many independently packaged components, each carrying its own terms, including the MIT, GPL, LGPL, BSD, Apache 2.0 and MPL licences. Every package's terms are readable with tdnf info <package> and under /usr/share/licenses/. No subscription, licence key or support contract is required to run it.

Azure Linux is Microsoft's own distribution. The name is used here to identify the distribution this image contains. This image is a hardened, repackaged cloudimg build of that distribution.

Support

For assistance with this image, contact cloudimg support: