Deployment guide

Rocky Linux 10 Minimal

Overview

This guide shows you how to deploy and configure Rocky Linux 10 Minimal on Microsoft Azure. It uses the pre-configured SecureAnyCloud virtual machine image from the Azure Marketplace.

Rocky Linux is a community-driven enterprise Linux distribution from the Rocky Enterprise Software Foundation. It is binary compatible with Red Hat Enterprise Linux 10. This is the Minimal edition. It removes the web console, the tuning daemon, the support report collector, the boot splash and the firmware bundle for physical hardware that an Azure guest never has. The result is a smaller installed package set and a smaller surface to patch and audit.

The SecureAnyCloud Rocky Linux 10.2 image is pinned to a single point release. This listing is different: it tracks whichever 10.x point release is current at build time, so it always reports the latest Rocky Linux 10 stream.

What you get:

  • Rocky Linux 10, binary compatible with RHEL 10, Minimal edition
  • 430 installed packages on a fresh build, roughly 1.1 GB on disk. cockpit, tuned, sos, plymouth, linux-firmware and the GeoIP data files are removed, and everything the platform needs to boot, network, authenticate and update itself is kept intact
  • Every available update applied at build time, verified with a zero-pending check
  • Unattended updates already armed, 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, with its policy verified present, both at runtime and persisted for the next boot
  • BaseOS, AppStream and Extras repositories enabled, with signature checking on
  • Exactly one externally reachable port: SSH on 22
  • Gen2 Hyper-V virtual machine support
  • 24/7 SecureAnyCloud 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.
  • KbdInteractiveAuthentication is also disabled, closing the other password path.
  • PermitRootLogin is set to 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.
  • No SSH host keys are baked into the image. Each machine generates its own at first boot, so two machines built from this image never share a host identity.
  • /etc/machine-id ships empty and is regenerated per machine.
  • SELinux is left in enforcing mode, the Rocky Linux default, with its selinux-policy-targeted policy package verified present on the image. The build checks the policy itself, not only the runtime mode.

Prerequisites

Before you deploy this image, make sure you have:

  • An active Microsoft Azure subscription
  • Access to the Azure Portal or Azure CLI
  • An SSH key pair for Linux VM access
  • Familiarity with Azure VM management

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

1

Deploy the Virtual Machine

Option A: Azure Portal

  • Go to the Azure Marketplace and search for "Rocky Linux 10 Minimal SecureAnyCloud".
  • Select the image and choose Create.
  • Configure the basics:
  • Subscription: Select your Azure subscription
  • Resource Group: Create new or select existing
  • Virtual Machine Name: Enter a name for your VM
  • Region: Select your preferred Azure region
  • Size: Standard_B2s 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:rocky-10-minimal:default:latest
az vm create \
  --resource-group myResourceGroup \
  --name my-rocky-10-minimal-vm \
  --image sac1647283583153:rocky-10-minimal:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
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-rocky-10-minimal-vm --show-details --query publicIps -o tsv ssh azureuser@<vm-ip>

There is no password to enter. If SSH asks for one, your client is not offering the key you supplied when you created the VM.

3

Confirm the release

Check the Rocky Linux release and package count:

cat /etc/rocky-release grep -E '^(NAME|VERSION|ID|PLATFORM_ID)=' /etc/os-release uname -rm rpm -qa | wc -l

Expected output:

Rocky Linux release 10.2 (Red Quartz) NAME="Rocky Linux" VERSION="10.2 (Red Quartz)" ID="rocky" PLATFORM_ID="platform:el10" 6.12.0-211.44.1.el10_2.x86_64 x86_64 430

This listing moves forward with the Rocky Linux 10 stream. It ships whichever 10.x point release is current when the image is built. It is not pinned to a single minor release like the SecureAnyCloud Rocky Linux 10.2 image.

4

Check the patch level

The image is fully updated at build time. dnf check-update returns exit code 100 when updates are pending and 0 when none are:

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

Confirm no reboot is outstanding. needs-restarting -r returns 0 when nothing requires a restart:

sudo dnf needs-restarting -r echo "needs-restarting exit code: $?"

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

dnf repolist --enabled

Expected output:

repo id repo name appstream Rocky Linux 10 - AppStream baseos Rocky Linux 10 - BaseOS extras Rocky Linux 10 - Extras

CodeReady Builder (crb) is not enabled on this image. It carries developer and build-time packages that most server workloads do not need. Enable it yourself if you need it:

echo "crb state: $(dnf repolist --all 2>/dev/null | grep -c '^crb ')"

To turn it on, run sudo dnf config-manager --set-enabled crb.

Package signatures are verified on every install: no repository on this image sets gpgcheck=0.

5

Unattended updates are already armed

This image ships patched and keeps patching itself. dnf-automatic is installed and configured to apply updates, and its timer is enabled so it starts on every boot:

systemctl is-enabled dnf-automatic.timer
systemctl is-active dnf-automatic.timer grep -E '^(upgrade_type|download_updates|apply_updates)' /etc/dnf/automatic.conf

Expected output:

enabled active upgrade_type = default download_updates = yes apply_updates = yes

upgrade_type is deliberately set to default rather than security. The security-only mode resolves against errata metadata. Where that metadata is not published, a security-only policy silently resolves to nothing and applies no updates at all. Setting default applies every available update, so it cannot quietly do nothing.

To control the schedule yourself, disable the timer and patch on your own cadence:

echo "to take manual control: sudo systemctl disable --now dnf-automatic.timer"

To patch by hand at any time, run sudo dnf upgrade -y, then reboot with sudo systemctl reboot if a new kernel was installed.

6

Verify the security posture

Confirm that SELinux is enforcing with its policy loaded, root is locked, SSH is key-only, and there is no swap:

getenforce grep -E '^[[:space:]]*SELINUX=' /etc/selinux/config rpm -q selinux-policy-targeted
sudo passwd -S root
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication)' swapon --show

Expected output:

Enforcing SELINUX=enforcing selinux-policy-targeted-42.1.18-4.el10_2.2.noarch root L 2009-12-22 -1 -1 -1 -1 permitrootlogin without-password passwordauthentication no kbdinteractiveauthentication no

The swapon --show command returns nothing. That is expected (see Step 7).

without-password is how OpenSSH reports the prohibit-password setting. Both names mean the same thing: root may not authenticate with a password.

The checks cover the runtime SELinux mode, the persisted /etc/selinux/config value and the selinux-policy-targeted package itself. Checking the package matters. A minimal trim that removed the policy package by accident could still produce plausible getenforce output until the system falls back to Permissive with no policy loaded. That failure is materially worse than a config file that is simply set to permissive.

7

Verify Azure integration and resources

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

systemctl is-active waagent
systemctl is-enabled waagent cloud-init --version
systemctl is-active chronyd df -h / free -h

Note that free -h reports 0B of swap. That is deliberate. Azure manages swap on the ephemeral resource disk through waagent rather than on the OS disk, and a swap file baked into a Marketplace image fails certification. If your workload needs swap, configure it through waagent.

8

Networking and open ports

The Azure Network Security Group (NSG) controls inbound and outbound traffic. It is usually the only place you need to open a port.

This image is a Minimal build, so firewalld is not installed. That is deliberate. With no host firewall in the way, your NSG rules take effect exactly as written, and there is no second layer to keep in sync. Confirm what is listening before you open anything:

ss -tlnu

On a fresh machine, SSH on port 22 is the only externally bound listener. Chrony appears on 127.0.0.1:323, which is loopback only and not reachable from the network.

rpcbind is disabled on this image (where present on the base at all). The stock Rocky Linux cloud image can enable it because nfs-utils depends on it, which would otherwise leave TCP and UDP port 111 open on every interface. NFSv4, the default in Rocky Linux 10, does not use rpcbind at all. This image therefore keeps rpcbind disabled and the port closed, while nfs-utils stays installed and fully working for NFSv4 mounts:

echo "rpcbind.socket: $(systemctl is-enabled rpcbind.socket 2>/dev/null || echo disabled)" rpm -q nfs-utils

If you need NFSv3, which does require the portmapper, turn rpcbind back on with one command:

echo "to re-enable NFSv3 support: sudo systemctl enable --now rpcbind.socket"

rpcbind is disabled rather than masked, so that command works without further steps.

If your policy also requires a host firewall, install and enable it yourself:

sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-port=443/tcp sudo firewall-cmd --reload

Once firewalld is running, open each port in both the Azure NSG and firewalld. Traffic does not reach your service until both allow it.

9

What the Minimal edition trims, and what it never touches

This is the same Rocky Linux 10 base as the standard SecureAnyCloud images, with the packages that a headless Azure guest never uses removed. Confirm the trim for yourself:

rpm -qa cockpit-ws cockpit-bridge tuned sos plymouth linux-firmware echo "(no output above = every trimmed package is genuinely absent)"

Removed Why it is safe to remove on Azure

linux-firmware Firmware blobs for physical NICs, GPUs, wireless and storage controllers. An Azure guest's storage and network are the in-kernel Hyper-V synthetic drivers, which load no firmware at all. This is the single largest reduction.

cockpit-ws, cockpit-bridge The web admin console. This is a headless server image with no web UI.

tuned The tuning-profile daemon. Azure images use the platform defaults.

sos The Red Hat support-report collector. Install it yourself if you need it for a support case.

plymouth The graphical boot splash. There is no console to splash to on a cloud VM.

GeoIP data files A bundled dataset unused on a base OS image.

Nothing the platform needs is touched. systemd, NetworkManager, openssh-server, cloud-init, WALinuxAgent, dnf, sudo, chrony and dnf-automatic all ship exactly as on the standard image.

SELinux packages are never trim candidates on this image. selinux-policy, selinux-policy-targeted and the rpm-plugin-selinux/libselinux/cockpit-ws-selinux family are excluded from the trim outright, because removing the wrong Cockpit sub-package can otherwise cascade-remove the SELinux policy itself. Every removal above is verified on the image before it is captured. SELinux enforcing with its policy loaded is checked as a separate, mandatory gate.

10

Install software

AppStream carries the application packages. Search it, then install what you need:

dnf search nginx

Rocky Linux 10 has moved away from DNF4 module streams, and modularity is deprecated on this platform. As a result, dnf module list exits non-zero and reports "No matching Modules to list" for most packages, including nginx. That is expected and is not an error in your setup. AppStream now carries a single current version of each package rather than several parallel streams to choose between:

dnf module list nginx || echo "(modularity is deprecated on Rocky Linux 10 — this is expected)"

Expected output:

WARNING: modularity is deprecated, and functionality will be removed in a future release of DNF5. Error: No matching Modules to list (modularity is deprecated on Rocky Linux 10 — this is expected)

Install a package and enable it in the usual way. For example, run sudo dnf install -y nginx, then sudo systemctl enable --now nginx.

To add another administrator, create the account with sudo adduser <name>. Add it to the wheel group with sudo usermod -aG 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, so azureuser is the only login until you add one:

getent group wheel

Common Use Cases

  • A stripped-down, RHEL-compatible base for production servers where a smaller package set matters
  • A lean foundation for your own applications and container hosts
  • Migrating RHEL-compatible workloads without licence cost, using the minimal-footprint edition

Troubleshooting

Cannot connect via SSH

  • Check that the VM is in the Running state in the Azure Portal.
  • Check that port 22 is allowed in the Network Security Group.
  • Use the correct username: azureuser.
  • Check that your SSH key matches the one you supplied when you created the VM. Password login is disabled by design, so a wrong key cannot fall back to a password prompt.

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

Azure agent not running

systemctl is-active waagent

If the agent is not running, start it. Run this on the VM:

sudo systemctl enable --now waagent

Package manager issues

Refresh the metadata cache first:

sudo dnf clean all
sudo dnf makecache

If the repositories are unreachable, check DNS resolution. This image is minimal, so nslookup and dig are not installed. getent is always present and resolves through the same system resolver:

getent hosts download.rockylinux.org

To get dig and nslookup, install bind-utils.

A service is blocked and the logs mention SELinux

SELinux is enforcing on this image. Do not disable it. Look at what was denied instead. On a healthy machine there are no recent denials, so the command reports none:

sudo ausearch -m AVC -ts recent 2>/dev/null || echo "no recent AVC denials"

If a denial is genuine, set the correct file context with semanage fcontext and restorecon, or enable the relevant boolean with setsebool -P. Do not turn SELinux off.

Checking for failed services

A healthy machine reports running with nothing failed:

systemctl is-system-running
systemctl list-units --state=failed --no-legend

I need something the Minimal trim removed

Nothing is blocked. These packages are only absent by default. cockpit-ws, tuned, sos, plymouth and firewalld all install cleanly from the enabled repositories with a normal sudo dnf install -y <package> command if your workload needs them.

Important Notes

Rocky Linux is free and open source software, and it is a collection of licences rather than a single one. This image carries 430 installed packages, which between them declare 126 distinct licence strings, most commonly LGPL-2.1-or-later, GPL-2.0-or-later, MIT, GPL-3.0-or-later, GPL-2.0-only, BSD-3-Clause and LGPL-3.0-or-later. Each package's own terms are readable on the machine:

rpm -qa --qf '%{LICENSE}\n' | sort | uniq -c | sort -rn | awk 'NR<=8'

No subscription, licence key or support contract is required for any of it.

This image tracks the current 10.x point release and is not pinned to one. If you need a specific, named point release, use the SecureAnyCloud Rocky Linux 10.2 image.

Support

For help with this image, contact SecureAnyCloud support:

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

Deploy on Azure

Launch Rocky Linux 10 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