Deployment guide

AlmaLinux 9.7

Overview

AlmaLinux is a community-owned enterprise Linux distribution, produced by the AlmaLinux OS Foundation to be binary compatible with Red Hat Enterprise Linux 9. Version 9.7 is a point release in the RHEL 9 family. This SecureAnyCloud image is frozen to it: every package is pinned to the archived 9.7 vault snapshot, so the platform you certify against today is the exact platform you keep.

The image is built for reproducible and compliance environments that must not drift to a newer minor release. It runs on Microsoft Azure (Gen2 Hyper-V) with default user azureuser.

What you get:

  • AlmaLinux 9.7, binary compatible with RHEL 9, pinned to the 9.7 vault snapshot
  • Every package synced to the 9.7 vault, verified with a zero-pending check at build time
  • Unattended updates armed against the frozen 9.7 vault, so the machine applies 9.7 errata without ever rolling forward to 9.8
  • 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, AppStream, CRB and Extras vault repositories enabled, with signature checking on
  • Exactly one externally reachable port: SSH on 22
  • Gen2 Hyper-V virtual machine support
  • 24/7 SecureAnyCloud support

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 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 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 stays in enforcing mode, the AlmaLinux 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_B2s (2 vCPU, 4 GB RAM) or larger.

1

Deploy the virtual machine

Option A: Azure Portal

  • Open the Azure Marketplace and search for "AlmaLinux 9.7 SecureAnyCloud".
  • Select the image and click Create.
  • Configure the basics:
  • Subscription: select your Azure subscription.
  • Resource Group: create a new group 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).
  • Click Review + Create, then Create.

Option B: Azure CLI

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

Connect via 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-almalinux-9-7-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.

3

Confirm the release

Check that the machine is the AlmaLinux 9.7 release you expect:

cat /etc/almalinux-release grep -E '^(NAME|VERSION|ID|PLATFORM_ID)=' /etc/os-release uname -rm

Expected output:

AlmaLinux release 9.7 (Moss Jungle Cat) NAME="AlmaLinux" VERSION="9.7 (Moss Jungle Cat)" ID="almalinux" PLATFORM_ID="platform:el9" 5.14.0-611.55.1.el9_7.x86_64 x86_64

The kernel version carries an el9_7 tag, which marks the machine as being on the 9.7 stream. Because this image is frozen to the 9.7 vault, the tag stays el9_7 for the life of the machine.

4

Check the patch level

The image is fully synced to the 9.7 vault at build time. dnf check-update returns exit code 100 when updates are pending against the enabled repositories, and 0 when none are. Because the machine is pinned to the frozen 9.7 vault, it reports 0:

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

Confirm that 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 the update path is the vault:

dnf repolist --enabled

Expected output:

repo id repo name appstream-vault-9-7 AlmaLinux 9.7 - AppStream (vault, frozen) baseos-vault-9-7 AlmaLinux 9.7 - BaseOS (vault, frozen) crb-vault-9-7 AlmaLinux 9.7 - CRB (vault, frozen) extras-vault-9-7 AlmaLinux 9.7 - extras (vault, frozen)

Package signatures are verified on every install. No repository on this image sets gpgcheck=0, and the vault packages are signed with the same AlmaLinux 9 GPG key.

5

This image is frozen to the 9.7 vault

This is the defining property of this image, and the reason to choose it over the rolling AlmaLinux 9 image. Every repository points at the archived 9.7 vault at repo.almalinux.org/vault/9.7/. The rolling mirrorlist and metalink resolvers are disabled, so nothing can pull the machine forward to 9.8:

grep -h baseurl /etc/yum.repos.d/almalinux-vault-9.7.repo | head -2
grep -rlE '^[[:space:]]*(mirrorlist|metalink)=' /etc/yum.repos.d/ 2>/dev/null || echo "no rolling resolver present"

Expected output:

baseurl=https://repo.almalinux.org/vault/9.7/BaseOS/$basearch/os/ baseurl=https://repo.almalinux.org/vault/9.7/AppStream/$basearch/os/ no rolling resolver present

Unattended updates are armed, but only against the frozen vault. dnf-automatic applies any errata published within the 9.7 stream and never rolls the machine to a newer minor release:

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

Expected output:

enabled upgrade_type = default download_updates = yes apply_updates = yes

If you want to track whichever AlmaLinux 9 release is current, this frozen image is not the right choice. Use the SecureAnyCloud AlmaLinux 9 image, which follows the rolling stream, or the SecureAnyCloud AlmaLinux 9.8 image for the current point release. You can also convert this machine to the rolling channel yourself:

echo "to move to the rolling 9 stream: sudo dnf reinstall -y almalinux-repos && sudo rm /etc/yum.repos.d/almalinux-vault-9.7.repo && sudo dnf distro-sync -y"

This command reinstates the stock repository definitions, removes the vault pin, and lets the machine move to the current 9 series minor release. Leave the vault in place to keep the machine reproducible.

6

Verify the security posture

Confirm that SELinux is enforcing, root is locked and SSH is key-only:

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

Expected output:

Enforcing SELINUX=enforcing root LK 2009-12-22 -1 -1 -1 -1 (Alternate authentication scheme in use.) permitrootlogin without-password pubkeyauthentication yes passwordauthentication no kbdinteractiveauthentication no

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

The commands check both the runtime mode and the persisted /etc/selinux/config value, because a runtime setting that is not persisted silently reverts on your next reboot.

7

Verify Azure integration

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

waagent lets Azure provision your SSH key, resize the OS disk, run extensions and report VM health, so it should always be active and enabled.

Note that free -h reports 0B of swap. This 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

Review networking and open ports

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

This image is a minimal build, so firewalld is not installed. This is deliberate. With no host firewall in the way, 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 -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. The stock AlmaLinux cloud image enables it because nfs-utils depends on it, which leaves TCP and UDP port 111 open on every interface. NFSv4, the default in AlmaLinux 9, does not use rpcbind at all. This image therefore disables rpcbind and closes the port, while keeping nfs-utils 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 requires 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 this 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, a port must be open in both the Azure NSG and firewalld before traffic reaches your service.

9

Install software

AppStream carries the application packages, served from the 9.7 vault. Search AppStream, then install what you need:

dnf search nginx

Install a package and enable it in the usual way, for example sudo dnf install -y nginx followed by sudo systemctl enable --now nginx. Everything you install comes from the frozen 9.7 vault, so a package you add today resolves to the same version on a machine you build from this image next year.

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 wheel

Common use cases

  • Reproducible and compliance builds pinned to a fixed minor release
  • Certifying software against an exact 9.7 platform
  • A stable base for long-lived workloads that must not drift to a newer minor release
  • Recreating a historical environment for audit or forensic work

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 NSG.
  • Use the correct username: azureuser.
  • Verify that 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 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 command on the VM:

sudo systemctl enable --now waagent

Package manager issues

Refresh the metadata cache first:

sudo dnf clean all
sudo dnf makecache

If 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 repo.almalinux.org

Install bind-utils if you want dig and nslookup available.

A service is blocked and the logs mention SELinux

SELinux is enforcing on this image. Instead of disabling it, inspect what was denied. 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, rather than turning 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

Important notes

AlmaLinux is free and open source, and it is a collection of licences rather than a single one. This image carries 419 installed packages that declare 99 distinct licence strings between them, most commonly LGPLv2+, GPLv2+, MIT, GPLv3+, BSD, GPLv2, LGPLv3+ and Public Domain. You can read each package's own terms 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.

AlmaLinux 9 is supported until May 2032. This image is frozen to the 9.7 point release through the archived vault, which suits a reproducible or compliance environment. To track whichever 9 series release is current, use the SecureAnyCloud AlmaLinux 9 image instead, or the SecureAnyCloud AlmaLinux 9.8 image for the current point release.

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 AlmaLinux 9.7 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