Operating Systems Azure

CentOS Stream 9 Minimal on Azure User Guide

| Product: CentOS Stream 9 Minimal on Azure

Overview

This guide covers the deployment and configuration of CentOS Stream 9 Minimal on Microsoft Azure using cloudimg's pre configured virtual machine image from the Azure Marketplace.

CentOS Stream is a free, open source Linux distribution maintained by the CentOS Project and sponsored by Red Hat. Stream 9 is the continuously delivered development branch that sits just ahead of Red Hat Enterprise Linux 9, so it tracks what the next RHEL 9 update will contain while remaining binary compatible with the RHEL 9 platform. This is the Minimal edition: the same CentOS Stream 9 with the desktop era and support tooling a headless cloud server never uses removed, so the machine you run has a smaller installed package set and a smaller attack surface to patch and audit.

The upstream CentOS Stream 9 GenericCloud image is already leaner than a full AlmaLinux or Rocky Linux cloud image, so there is no single dominant package to remove here. What Minimal changes is the package set: the Cockpit web console, the sosreport support collector and the bundled GeoIP datasets are removed. Each is one fewer service or dataset to keep patched and account for in a security review.

What's included:

  • CentOS Stream 9, the continuously-delivered upstream development branch of RHEL 9, rolled forward to the current package set at build time
  • A reduced package set: no Cockpit web console, no sosreport, no bundled GeoIP datasets
  • Every available update applied at build time, verified with a zero pending check
  • Unattended updates already armed (dnf-automatic), so the machine keeps patching itself
  • Azure Linux Agent (waagent) and cloud-init for Azure integration
  • Chronyd for NTP time synchronisation
  • SELinux in enforcing mode, both at runtime and persisted for the next boot
  • BaseOS and AppStream repositories enabled, with signature checking on
  • Exactly one externally reachable port: SSH on 22
  • Gen1 Hyper-V virtual machine support
  • 24/7 cloudimg support

Platform: Microsoft Azure (Gen1 Hyper-V) Default user: azureuser

What "Minimal" means here, precisely

The upstream CentOS Stream 9 GenericCloud image this offer is built from does not ship linux-firmware, tuned or plymouth in the first place — it is already a lean cloud image, unlike a full desktop-oriented AlmaLinux or Rocky Linux base. So the Minimal trim here is smaller in absolute terms than on those sibling images, and is reported honestly rather than assumed: on this build the package count moved from 401 packages at base boot to 388 packages in the shipped image, and root filesystem usage measured 1.3G used on the 10G root disk after the trim, the security patch pass, and arming unattended updates. Removed from the base: the Cockpit web console (a network facing management surface), the sosreport support collector, and the bundled GeoLite2 datasets. Each is one fewer service or dataset to keep patched and to account for in a security review — which is the reason a compliance driven deployment chooses a Minimal image.

What is deliberately kept: systemd, NetworkManager, the SSH server, cloud-init, the Azure Linux Agent, dnf, sudo, chrony and dnf-automatic. The build fails closed if any of those is missing after the trim.

Confirm the footprint on your own machine:

df -h / | awk 'NR==2 {print "root filesystem used: " $3}'
rpm -qa | wc -l

Expected output (yours will track whatever has patched since this image was built):

root filesystem used: 1.3G
388

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.
  • KbdInteractiveAuthentication is also disabled, closing the other password path.
  • PermitRootLogin is set to without-password (also written as prohibit-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.
  • SSH host keys are not baked into the image. cloud-init regenerates them on every machine, so no two customers share a host identity.
  • SELinux runs in enforcing mode, both at runtime and persisted in /etc/selinux/config, so mandatory access control is active from first boot.

Verify the effective SSH configuration on your own machine, reading the parsed values rather than the file text:

sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|permitemptypasswords) '

Expected output:

permitrootlogin without-password
passwordauthentication no
kbdinteractiveauthentication no
permitemptypasswords no

1. Deploy the virtual machine

Option A: Azure Portal

  1. Navigate to the Azure Marketplace and search for "CentOS Stream 9 Minimal 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-centos-stream-9-minimal-vm \
  --image cloudimg:centos-stream:stream9-minimal:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

2. Connect via SSH

Once your VM is running, connect using SSH:

ssh azureuser@<YOUR-VM-IP>

To find your VM's public IP (run this on your own machine, with the Azure CLI, not on the VM itself):

az vm show --resource-group myResourceGroup --name my-centos-stream-9-minimal-vm --show-details --query publicIps -o tsv

3. Confirm the release and patch level

cat /etc/centos-release

Expected output:

CentOS Stream release 9

CentOS Stream 9 is continuously delivered (rolling) rather than minor-pinned, so this always reports the current Stream 9 identity. Confirm nothing is outstanding:

sudo dnf -q check-update >/dev/null 2>&1; echo "check-update rc=$? (100 would mean updates pending)"

4. Confirm the trim actually shipped

The packages a cloud guest cannot use should be absent, and the platform essentials present:

for p in linux-firmware tuned cockpit sos plymouth; do rpm -q $p >/dev/null 2>&1 && echo "$p: present" || echo "$p: absent"; done
for p in systemd NetworkManager openssh-server cloud-init WALinuxAgent dnf sudo chrony; do rpm -q $p >/dev/null 2>&1 && echo "$p: present" || echo "$p: MISSING"; done

5. Confirm Azure integration and SELinux

systemctl is-active waagent.service
getenforce

Expected: active and Enforcing.

6. Unattended updates

The image arms dnf-automatic so the machine keeps patching itself after you deploy it:

systemctl is-enabled dnf-automatic.timer

Expected output: enabled.

7. Configure firewall (optional)

The Azure Network Security Group (NSG) is the primary inbound and outbound traffic control and is recommended for most deployments. This image does not ship a host firewall daemon (firewalld is not preinstalled); the base iptables command is present. If you want a host firewall in addition to the NSG, install and enable firewalld first:

sudo dnf install -y firewalld
sudo systemctl enable --now firewalld

With firewalld running you can inspect the active ruleset:

sudo firewall-cmd --list-all

8. Adding software back

Nothing about the trim prevents you installing anything you need — the full CentOS Stream repositories are enabled and signature checked. Cockpit, for example, can be reinstalled if you want the web console:

sudo dnf install -y cockpit
sudo systemctl enable --now cockpit.socket

Common use cases

  • A stripped down, RHEL 9 compatible base for production servers where a smaller package set matters
  • Tracking and testing against the next RHEL 9 update ahead of general availability, minimal footprint edition
  • A lean foundation for your own applications, container hosts and CI runners

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 configured during deployment

Azure agent not running

sudo systemctl start waagent
sudo systemctl enable waagent

Package manager issues

sudo dnf upgrade -y

Important notes

CentOS Stream is free and open source (GPLv2 and a collection of upstream open-source licences). It is the upstream development branch of Red Hat Enterprise Linux 9, sponsored by Red Hat and maintained by the CentOS Project. No licence or paid subscription is required.

Support

cloudimg provides 24/7 support for this image at support@cloudimg.co.uk.