Deployment guide

CentOS Stream 9 Minimal

Overview

This guide covers how to deploy and configure CentOS Stream 9 Minimal on Microsoft Azure. It uses SecureAnyCloud's preconfigured 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. It tracks what the next RHEL 9 update will contain while remaining binary compatible with the RHEL 9 platform.

This is the Minimal edition. It is the same CentOS Stream 9, with the desktop-era and support tooling that a headless cloud server never uses removed. 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 no single dominant package needs removing here. Minimal changes the package set instead. It removes the Cockpit web console, the sosreport support collector and the bundled GeoIP datasets. Each is one fewer service or dataset to keep patched and account for in a security review.

What you get:

  • 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, with no Cockpit web console, no sosreport and 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
  • The 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 SecureAnyCloud support

The platform is Microsoft Azure (Gen1 Hyper-V). The default user is azureuser.

What "Minimal" means here

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. The Minimal trim is therefore smaller in absolute terms than on those sibling images.

The measured results on this build are as follows. The package count moved from 401 packages at base boot to 388 packages in the shipped image. Root filesystem usage measured 1.3G used on the 10G root disk after the trim, the security patch pass and arming unattended updates.

The trim removed 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. That is why compliance-driven deployments choose a Minimal image.

The image deliberately keeps systemd, NetworkManager, the SSH server, cloud-init, the Azure Linux Agent, dnf, sudo, chrony and dnf-automatic. The build fails closed if any of them 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 reflect any patches released 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, which closes 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 is set later.
  • 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. This reads 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

  • Go to the Azure Marketplace and search for "CentOS Stream 9 Minimal SecureAnyCloud".
  • Select the image and choose Create.
  • Configure the basics:
  • Subscription: select your Azure subscription.
  • Resource group: create a new one or select an existing one.
  • Virtual machine name: enter a name for your VM.
  • Region: select your preferred Azure region.
  • Size: Standard_B2s is recommended.
  • Under Administrator account, select SSH public key and enter your key.
  • Under Inbound port rules, allow SSH (port 22).
  • Choose Review + create, then Create.

Option B: Azure CLI

az vm image terms accept --urn sac1647283583153:centos-stream-9-minimal:default:latest
az vm create \
  --resource-group myResourceGroup \
  --name my-centos-stream-9-minimal-vm \
  --image sac1647283583153:centos-stream-9-minimal:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

2. Connect via SSH

When your VM is running, connect over 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 pinned to a minor release, so this always reports the current Stream 9 identity. Next, confirm that 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 shipped

The packages a cloud guest cannot use should be absent, and the platform essentials should be 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 the firewall (optional)

The Azure Network Security Group (NSG) is the primary control for inbound and outbound traffic, and most deployments should rely on it. This image does not ship a host firewall daemon, because 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, inspect the active ruleset:

sudo firewall-cmd --list-all

8. Adding software back

The trim does not stop you from installing anything you need. The full CentOS Stream repositories are enabled and signature-checked. For example, you can reinstall Cockpit 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, with a minimal footprint
  • A lean foundation for your own applications, container hosts and CI runners

Troubleshooting

Cannot connect via SSH

  • Verify that the VM is in the Running state in the Azure Portal.
  • Check that port 22 is allowed in the Network Security Group.
  • Make sure you are using the correct username: azureuser.
  • Verify that 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

SecureAnyCloud provides 24/7 support for this image. Contact sales@secureanycloud.com.

  • Website: secureanycloud.com
  • Product catalogue: secureanycloud.com/products
  • User guides: secureanycloud.com/guides
  • SLA: 24-hour response guaranteed

Deploy on Azure

Launch CentOS Stream 9 Minimal 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