Rocky 9 arm64
Overview
Rocky Linux is a community enterprise Linux distribution produced by the Rocky Enterprise Software Foundation to be binary compatible with Red Hat Enterprise Linux. This SecureAnyCloud image is a preconfigured, native Arm (AArch64/arm64) build of Rocky Linux 9 for Microsoft Azure, deployed from the Azure Marketplace.
It runs the 5.14 kernel and follows the RHEL 9 lifecycle. It runs on Azure's Arm virtual machine sizes, the Ampere Altra-based Dpsv6 and Dplsv6 families, where many workloads deliver the same performance at a lower cost than on x86.
What you get:
- Rocky Linux 9, native 64-bit Arm (arm64 / AArch64), binary compatible with RHEL 9
- Every available update applied at build time
- Automatic updates enabled, so the machine keeps patching itself
- Azure Linux Agent (waagent) and cloud-init for Azure integration
- Chronyd for NTP time synchronization
- SELinux in enforcing mode
- BaseOS and AppStream repositories enabled, so your update path stays intact
- No swap on the operating system disk
- Gen2 Hyper-V virtual machine support
- 24/7 SecureAnyCloud support
Platform: Microsoft Azure (Gen2 Hyper-V, Arm64). Default user: azureuser.
This is the Rocky Linux 9 major release, on Arm
This listing tracks the Rocky Linux 9 major release, not a frozen minor release. RHEL-family security backports roll into the latest minor stream. The image is therefore built from whichever Rocky Linux 9 point release is current at build time and brought fully up to date.
Your own dnf update then rolls the machine forward within Rocky Linux 9 in the normal way, so you keep receiving security fixes. If your change control requires an exact minor version, SecureAnyCloud also publishes point-release-pinned Rocky Linux 9 images on x86.
This Arm build is a separate product from the x86 Rocky Linux 9 images. It carries aarch64 packages and an aarch64 kernel, and it runs only on Arm virtual machine sizes.
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.
- No account on the image has a usable password.
PasswordAuthenticationis disabled in the SSH daemon, so every login is by key.PermitRootLoginis set towithout-password, so root cannot be reached with a password. No root key ships in the image, so root has no remote login until you create one deliberately.- SSH host keys are removed before capture and regenerated on each machine at first boot, so no two machines you launch share a host identity.
/etc/machine-idis cleared before capture and regenerated per machine.- The only key that works is the public key you supply when you create the virtual machine. Azure injects it into
azureuserat first boot. - SELinux is left in enforcing mode, the Rocky Linux default.
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_D2ps_v6 (2 vCPU, 8 GB RAM) or larger.
This is an Arm64 image, so you must launch it on an Arm virtual machine size. Use the Dpsv6/Dplsv6 (Ampere Altra) families, or another Arm size with a p in its family name. An x86 size such as Standard_B2s will not boot this image.
Deploy the Virtual Machine
Option A: Azure Portal
- Open the Azure Marketplace and search for "Rocky Linux 9 Arm64 SecureAnyCloud".
- Select the image and click Create.
- On the Basics tab, set Subscription to your Azure subscription.
- Set Resource Group to a new or existing group.
- Enter a Virtual Machine Name.
- Pick your preferred Region.
- Set Size to
Standard_D2ps_v6(recommended, an Arm64 size). - Under Administrator Account, select SSH public key and enter your key.
- Under Inbound Port Rules, allow SSH (port 22).
- Click Review + Create, then Create.
Option B: Azure CLI
Run this on your own workstation. Substitute your resource group, VM name and preferred region:
az vm image terms accept --urn sac1647283583153:rocky-9-arm64:default:latest
az vm create \
--resource-group myResourceGroup \
--name my-rocky-9-arm64-vm \
--image sac1647283583153:rocky-9-arm64:default:latest \
--size Standard_D2ps_v6 \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardThe --size must be an Arm64 size, such as Standard_D2ps_v6 above. Azure rejects an x86 size for an Arm image at create time.
Connect over SSH
Run these commands on your own workstation, not on the VM. Find the public IP, then connect:
az vm show --resource-group myResourceGroup --name my-rocky-9-arm64-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 at create time.
Confirm the release and the architecture
Check that the machine runs Rocky Linux 9 on Arm.
cat /etc/rocky-releaseRocky Linux release 9.8 (Blue Onyx)The os-release fields carry the same information in a machine-readable form, which configuration management tools read:
grep -E '^(NAME|VERSION|ID|VERSION_ID|PLATFORM_ID)=' /etc/os-releaseNAME="Rocky Linux" VERSION="9.8 (Blue Onyx)" ID="rocky" VERSION_ID="9.8" PLATFORM_ID="platform:el9"The distribution itself asserts its RHEL compatibility lineage:
cat /etc/redhat-releaseRocky Linux release 9.8 (Blue Onyx)The kernel string shows the architecture:
uname -srmLinux 5.14.0-687.44.1.el9_8.aarch64 aarch64aarch64 from uname confirms this is the native 64-bit Arm build, not an emulated or x86 image. The version reported is the Rocky Linux 9 point release the image was patched to. This listing tracks the 9 major release, so dnf update rolls it forward across future point releases.
Check the patch level and automatic updates
Every available update was applied when this image was built. The command dnf check-update exits 100 when updates are pending and 0 when none are:
dnf -q check-update >/dev/null 2>&1; echo "exit=$?"exit=0Nothing is waiting on a reboot:
dnf needs-restarting -rNo core libraries or services have been updated since boot-up. Reboot should not be necessary.The base repositories are enabled, so your update path is intact:
dnf repolist --enabledrepo id repo name appstream Rocky Linux 9 - AppStream baseos Rocky Linux 9 - BaseOS extras Rocky Linux 9 - ExtrasCRB (CodeReady Builder) ships configured but disabled, which is the Rocky Linux default. Enable it only if you build software that needs its development headers:
sudo dnf config-manager --set-enabled crbAutomatic updates
Unlike a stock Rocky Linux cloud image, this machine keeps patching itself. dnf-automatic is installed and its timer is enabled, so updates apply on a schedule:
systemctl is-enabled dnf-automatic.timerenabledsystemctl cat dnf-automatic.timer | grep -E 'OnCalendar|RandomizedDelaySec'OnCalendar=*-*-* 6:00 RandomizedDelaySec=60mThe policy applies all available updates, not only those tagged as security errata. It never reboots automatically, so a kernel update waits for a window you choose instead of restarting a production machine without warning:
grep -E '^(apply_updates|upgrade_type|download_updates|reboot)' /etc/dnf/automatic.confupgrade_type = default download_updates = yes apply_updates = yes reboot = never reboot_command = "shutdown -r +5 'Rebooting after applying package updates'"upgrade_type is deliberately default rather than security. Errata metadata is not always populated, so a security-only policy can silently resolve to applying nothing. The default setting is the one that actually keeps the machine current.
Because reboot = never, the reboot_command above is configured but never invoked. After a kernel update, check periodically whether a restart is owed, using the needs-restarting -r command above. To opt out entirely, run sudo systemctl disable --now dnf-automatic.timer.
Verify the security posture
Confirm SELinux is enforcing:
getenforceEnforcingConfirm the root account is locked. The LK in the second field means locked:
passwd -S rootroot LK 2009-12-22 -1 -1 -1 -1 (Alternate authentication scheme in use.)Confirm that no account on the machine has a usable password. This prints nothing on a clean image:
sudo awk -F: '($2 !~ /^[!*]/) && ($2 != "") {print $1}' /etc/shadowRead the SSH daemon's effective policy rather than the config file, because the running daemon is what a client actually meets:
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|pubkeyauthentication) 'permitrootlogin without-password pubkeyauthentication yes passwordauthentication noThere is no swap on the operating system disk. Azure manages swap on the ephemeral resource disk if your VM size has one, and a swap file baked into a Marketplace image is not permitted. This prints nothing:
swapon --showConfirm what is listening. On a freshly launched machine, sshd on port 22 is your remote access. The base OS also runs rpcbind on port 111 and chronyd, bound to the loopback address, for time synchronization:
ss -tulnH | awk '{print $1, $5}' | sort -utcp 0.0.0.0:111 tcp 0.0.0.0:22 tcp [::]:111 tcp [::]:22 udp 0.0.0.0:111 udp 127.0.0.1:323 udp [::1]:323 udp [::]:111The Azure Network Security Group controls inbound traffic. Only the ports you explicitly open in the NSG are reachable from outside the VM, regardless of what is bound locally.
If you do not use RPC-based services and want to close port 111 on the host as well, run sudo systemctl disable --now rpcbind.socket rpcbind.service to stop it.
Verify Azure integration
The Azure Linux Agent handles provisioning, extensions and the portal's serial console. Check the agent and the related package versions:
systemctl is-active waagent rpm -q WALinuxAgent cloud-init chronyactive WALinuxAgent-2.14.0.1-4.el9.noarch cloud-init-24.4-8.el9_8.1.rocky.0.1.noarch chrony-4.8-1.el9.aarch64Cloud-init should report done, which means provisioning finished cleanly:
cloud-init statusstatus: doneThe kernel puts a console on ttyAMA0, the Arm PL011 serial port. This makes boot diagnostics and the portal's serial console work when you cannot reach the machine over SSH. On x86 images the console is ttyS0. On Arm it is ttyAMA0.
grep -o 'console=ttyAMA0[^ ]*' /proc/cmdlineconsole=ttyAMA0Time synchronization runs through chronyd against the Azure host clock:
chronyc -n sources | head -4MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== #* PHC0 2 3 377 9 +9225ns[ +10us] +/- 9529ns ^- 144.202.41.38 4 6 37 12 +286us[ +287us] +/- 34msPHC0 is the Azure host clock, and it is the source chronyd selects (the * marks it). Public NTP servers remain as fallbacks.
Storage layout
The operating system disk is a 10 GB Gen2 disk with a simple, non-LVM layout: an EFI system partition, a /boot partition and an XFS root.
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTSNAME SIZE FSTYPE MOUNTPOINTS sda 10G ├─sda1 100M vfat /boot/efi ├─sda2 1000M xfs /boot └─sda3 8.9G xfs / sr0 1024Mdf -hT / /bootFilesystem Type Size Used Avail Use% Mounted on /dev/sda3 xfs 8.9G 1.2G 7.7G 14% / /dev/sda2 xfs 936M 407M 530M 44% /bootTwo things follow from this layout.
There is no ephemeral resource disk on Dpsv6. The recommended Standard_D2ps_v6 size has no local temporary disk, so nothing is mounted at /mnt. For fast local scratch storage, choose a Dpdsv6 size (the d denotes a local disk) or attach a managed data disk. Do not write scratch data to /mnt expecting a separate volume. On this size it is only a directory on the root filesystem.
Expand the root disk if you need more than 10 GB. First resize the managed disk in Azure (the VM must be deallocated). Then grow the partition and the filesystem in place. XFS grows online, so no reboot is needed after the disk is enlarged:
sudo dnf install -y cloud-utils-growpart
sudo growpart /dev/sda 3
sudo xfs_growfs /To attach persistent storage instead, add a managed data disk in the portal or with az vm disk attach. Then partition and format it, and add it to /etc/fstab keyed by UUID.
Networking and the firewall
The Azure Network Security Group controls inbound and outbound traffic. It is the first, and usually the only, place you need to open a port.
This image is a minimal build, so firewalld is not installed:
rpm -q firewalld || echo "(firewalld absent - the Azure NSG is your only firewall)"package firewalld is not installed (firewalld absent - the Azure NSG is your only firewall)This 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 -tlnpIf 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 --reloadOnce firewalld is running, a port must be open in both the Azure NSG and firewalld before traffic reaches your service.
Install software
AppStream carries the application packages. Search it, then install what you need:
dnf search nginxInstall a package and enable it in the usual way, for example sudo dnf install -y nginx followed by sudo systemctl enable --now nginx. Everything in the repositories is built for Arm, so dnf resolves aarch64 packages automatically. There is nothing extra to configure for the architecture.
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 on the file and mode 700 on the .ssh directory, both owned by that user.
The image ships with no human accounts, so azureuser is the only login until you add one:
getent group wheelwheel:x:10:Common Use Cases
- RHEL 9-compatible application hosting on cost-efficient Arm virtual machines
- Container platforms and cloud-native workloads on Arm
- A RHEL-compatible platform for workloads certified against RHEL 9, without a subscription
- Arm build and CI runners, and fleets managed by Ansible, Puppet or Salt
Troubleshooting
Cannot connect over SSH
Check that the Network Security Group allows inbound TCP 22 from your address and that the machine is running. Make sure your client offers the private key that matches the public key you supplied at create time. Password authentication is disabled, so a password prompt means key negotiation has already failed.
az vm show --resource-group myResourceGroup --name my-rocky-9-arm64-vm --show-details --query powerState -o tsvThe VM will not create or will not boot
This is an Arm64 image. It runs only on Arm virtual machine sizes: the Dpsv6/Dplsv6 Ampere families and other sizes with a p in the family name. If Azure rejects the size at create time, or the VM never becomes reachable, confirm that you selected an Arm size and not an x86 one such as Standard_B2s or Standard_D2s_v5.
Running out of space on the root filesystem
The image ships a 10 GB operating system disk. Check what is using the space, then expand the disk with the growpart and xfs_growfs steps in Step 7:
df -h /
sudo du -xh --max-depth=1 / 2>/dev/null | sort -h | tail -10Azure agent not running
systemctl status waagent --no-pager sudo journalctl -u waagent -n 50 --no-pagerIf waagent is stopped, extensions and portal features that depend on it stop working. Restart it with sudo systemctl restart waagent.
Package manager issues
Clear the metadata cache and rebuild it:
sudo dnf clean all
sudo dnf makecacheIf a repository is unreachable, confirm that the machine has outbound HTTPS and that DNS resolves. Rocky Linux's mirror system needs both.
A service is blocked and the logs mention SELinux
SELinux is enforcing, which is the secure default and should stay that way. Inspect the denial instead of disabling SELinux:
sudo ausearch -m AVC -ts recent 2>/dev/null || echo "no recent AVC denials"Most denials on a fresh machine come from software installed into a non-standard path. Relabel it with sudo restorecon -Rv /path before you consider any policy change.
Important Notes
Rocky Linux is free and open source. No single license covers it: the distribution is a collection of free and open source licenses across its package set, predominantly GPL, with LGPL, BSD, MIT, Apache and others. No subscription, entitlement or license key is required, and no per-seat cost applies.
Rocky Linux is a trademark of the Rocky Enterprise Software Foundation. SecureAnyCloud is not affiliated with or endorsed by the Rocky Enterprise Software Foundation, and uses the name only to identify the distribution this image contains.
Rocky Linux 9 follows the RHEL 9 lifecycle, with support running into 2032. Check the Rocky Linux release notes for the dates that apply to your deployment.
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 9 Arm64 on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com