Operating Systems Azure

CentOS 7.8 on Azure User Guide

| Product: CentOS 7.8 on Azure

Overview

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

CentOS Linux is a community rebuild of Red Hat Enterprise Linux, binary compatible with RHEL 7. This image is CentOS Linux 7.8.2003, the point release that corresponds to RHEL 7.8, and it is pinned there: every package repository points at the frozen 7.8.2003 vault, so updating the machine does not quietly walk it onto a later point release.

That pin is the reason this image exists, and it is the whole difference from the major level CentOS 7 listing, which ships the terminal 7.9.2009 release. Plenty of software is certified, supported, or simply known to work against one specific CentOS 7 point release rather than the CentOS 7 line as a whole, and a machine that drifts off that release is no longer the platform that was signed off.

The image is provided deliberately for legacy migration workloads: teams moving software that is still certified only on the CentOS 7 or RHEL 7 platform, and who need a clean, hardened base at a specific point release while they re platform.

End-of-life notice — read this first

CentOS Linux 7 reached end-of-life on 30 June 2024. The upstream CentOS Project no longer produces any updates for it, including security updates. Consequently:

  • This image is patched only to its capture date, from the frozen CentOS 7.8.2003 vault (vault.centos.org). No newer 7.8 packages exist upstream, so "fully patched" here means patched to the last packages the 7.8 vault ever published.
  • Because the image is deliberately pinned to 7.8, it also does not receive the packages published later in the CentOS 7 lifecycle for 7.9. That is the trade you are making by choosing a point release: reproducibility instead of currency. If you want the last CentOS 7 package set instead, use the CentOS 7 image.
  • After the end-of-life date, no further upstream security updates are published for any CentOS 7 release. Over time the image will carry unpatched vulnerabilities that cannot be remediated by updating CentOS 7, because upstream ships nothing further.
  • This image is provided for legacy migration use — running or testing software that is only certified on the CentOS 7 or RHEL 7 platform while you migrate. Plan a migration to a supported distribution such as AlmaLinux, Rocky Linux, CentOS Stream, or a current RHEL for any workload that must remain secure.

The stock CentOS 7 repositories point at mirror.centos.org, which was retired at end-of-life. This image has already repointed every repository to the CentOS 7.8.2003 vault, so yum keeps working — against the frozen 7.8 package set — out of the box.

What's included

  • CentOS Linux 7.8.2003 (Core), binary compatible with RHEL 7.8
  • A standard, non LVM, single partition xfs root on an MBR disk — the same layout the stock CentOS 7 cloud image ships
  • Repositories pinned to vault.centos.org/7.8.2003 so yum keeps working post end-of-life and the machine stays on the release you bought
  • Every available 7.8.2003 vault package applied at build time (patched to capture date)
  • Azure Linux Agent (WALinuxAgent) and cloud-init, so the machine provisions cleanly on Azure
  • The Hyper V storage and network drivers built into the initramfs, so the machine boots on Azure hardware
  • Root grows automatically at boot to fill whatever OS disk size you ask Azure for, via cloud-init's growpart and resizefs modules
  • Growth tooling preinstalled for manual use: growpart, xfs_growfs, partx
  • Chronyd for NTP time synchronisation
  • SELinux in enforcing mode
  • firewalld running with only the SSH service allowed
  • No rpcbind: the port 111 RPC listener a stock CentOS 7 carries is absent, and masked so it cannot return unnoticed
  • Exactly one kernel installed, so no stale kernel package lingers
  • Gen1 Hyper V virtual machine support (BIOS boot)
  • 24/7 cloudimg support

Platform: Microsoft Azure (Gen1 Hyper V, BIOS boot) 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.
  • PermitRootLogin is set to no, so root cannot be reached over SSH at all.
  • 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.
  • The machine identity and the SSH host keys are regenerated uniquely on every instance, so no two machines share a host key either.
  • SELinux is left in enforcing mode, the CentOS default.
  • The only port listening off the machine is SSH on 22. rpcbind, which binds 0.0.0.0:111 on a stock CentOS 7 install, is not installed at all here, and its socket unit is masked as well so that installing nfs-utils later cannot silently reopen the port.

These are the controls cloudimg can guarantee. They do not change the end-of-life position above: a hardened CentOS 7.8 is still a CentOS 7 that receives no further upstream security updates.

Prerequisites

Before deploying this image, ensure you have:

  1. An active Microsoft Azure subscription
  2. Access to the Azure Portal or Azure CLI
  3. An SSH key pair for Linux VM access
  4. Familiarity with Azure VM management

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

OS disk sizing: the image is 10 GB, all of which is the root partition. If you want more room, simply ask Azure for a larger OS disk at create time — the machine grows root to fill it on its own at first boot. Step 5 covers how that works and what to do if you enlarge the disk later.

Step 1: Deploy the Virtual Machine

Option A: Azure Portal

  1. Navigate to the Azure Marketplace and search for "CentOS 7.8 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 Disks, set the OS disk size if you want more than the 10 GB the image ships with
  11. Under Inbound Port Rules, allow SSH (port 22)
  12. Click Review + Create, then Create

Option B: Azure CLI

az vm create \
  --resource-group myResourceGroup \
  --name my-centos-78-vm \
  --image cloudimg:centos:centos78:latest \
  --size Standard_B2s \
  --os-disk-size-gb 32 \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Step 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-centos-78-vm --show-details --query publicIps -o tsv
ssh azureuser@<vm-ip>

There is no password to enter. If SSH asks you for one, the key you supplied at create time is not the key your client is offering.

Step 3: Confirm the point release

This is the check that matters most on this image. Confirm the machine is CentOS Linux 7.8.2003 and not some other CentOS 7:

cat /etc/centos-release
rpm -q centos-release
grep -E '^(NAME|VERSION|ID|VERSION_ID)=' /etc/os-release
uname -rm

Expected output:

CentOS Linux release 7.8.2003 (Core)
centos-release-7-8.2003.0.el7.centos.x86_64
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
VERSION_ID="7"
3.10.0-1127.19.1.el7.x86_64 x86_64

Two things to note. /etc/os-release reports VERSION_ID="7" on every CentOS 7 point release — the file simply does not carry the minor, which is exactly why /etc/centos-release and rpm -q centos-release are the fields to check. And 3.10.0-1127.19.1.el7 is the last kernel the 7.8 vault published, so seeing it here is the marker that the machine is at the end of the 7.8 package set rather than part way through it.

Terminal showing cat of etc centos-release reporting CentOS Linux release 7.8.2003 Core, rpm -q centos-release agreeing at 7-8.2003, os-release fields ID centos and VERSION_ID 7, and uname reporting the 3.10.0-1127.19.1.el7 kernel on x86_64

Step 4: Verify the disk layout

This image ships the standard CentOS 7 cloud layout: one plain xfs partition carrying the whole root filesystem, on an MBR partitioned disk. There is no LVM and no separate /boot. If you want an LVM root instead, cloudimg publishes that as a separate CentOS 7 LVM image.

lsblk -o NAME,TYPE,MOUNTPOINT,SIZE,FSTYPE
findmnt /
sudo blkid -p -s PTTYPE -o value /dev/sda

Expected output on a machine launched with the 32 GB OS disk from the Option B example above:

NAME   TYPE MOUNTPOINT  SIZE FSTYPE
fd0    disk               4K
sda    disk              32G
└─sda1 part /            32G xfs
sdb    disk               8G
└─sdb1 part /mnt          8G ext4
sr0    rom              630K
TARGET SOURCE    FSTYPE OPTIONS
/      /dev/sda1 xfs    rw,relatime,seclabel,attr2,inode64,noquota
dos

The image itself is 10 GB, but sda1 already reports 32 GB here: root was grown to fill the requested OS disk during first boot, before you ever logged in. Step 5 explains that.

/ is /dev/sda1 with TYPE part, not a device mapper volume — that is the proof this is the standard variant. dos is the MBR partition table, which is what a Gen1 BIOS boot machine needs. sdb is the Azure temporary resource disk, which every Azure VM gets, and fd0 and sr0 are the virtual floppy and CD-ROM the Gen1 platform presents; none of the three are part of the root filesystem.

Terminal showing lsblk with root on the single plain partition sda1 formatted xfs, findmnt confirming root is dev sda1 xfs, blkid reporting the dos MBR partition table, an absent sys firmware efi directory confirming BIOS boot, and growpart xfs_growfs and partx all present

Step 5: Growing the root filesystem

In the normal case there is nothing to do. cloud-init's growpart and resizefs modules run on this image at boot, so the root partition and the xfs filesystem on it are extended to fill whatever OS disk size you asked Azure for. Ask for 32 GB at create time and the machine comes up with a 32 GB root:

df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        32G  1.5G   31G   5% /

The same applies when you enlarge the disk later. Azure will not resize an OS disk while the VM is running — the request is rejected with Change in disk property of OS disk is not allowed when VM is running — so enlarging one is always a stop, resize, start cycle, and the grow happens on the way back up:

az vm deallocate --resource-group myResourceGroup --name my-centos-78-vm
az disk update --ids $(az vm show -g myResourceGroup -n my-centos-78-vm --query storageProfile.osDisk.managedDisk.id -o tsv) --size-gb 64
az vm start --resource-group myResourceGroup --name my-centos-78-vm

After it comes back, root has already claimed the new space:

sda     64G
└─sda1  64G
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        64G  1.3G   63G   3% /

Growing it by hand

The tooling is on the image if you ever need to drive the grow yourself — for instance if you have disabled cloud-init's growpart module, or you are recovering a machine whose partition and filesystem have drifted out of step:

sudo growpart /dev/sda 1
sudo xfs_growfs /
df -h /

On a healthy machine these are both no-ops, because the automatic grow has already happened. growpart says so plainly and exits non zero, which is the expected answer and not an error:

NOCHANGE: partition 1 is size 134215647. it cannot be grown

Because root is a plain partition rather than an LVM volume, it can only grow into free space at the end of its own disk; it cannot be spread across a second disk. Attach data disks and mount them separately, or use cloudimg's CentOS 7 LVM image if you need one filesystem spanning several disks.

Step 6: The vault update path and the 7.8 pin

Because CentOS 7 is end-of-life, its original mirrors are gone. This image repoints every repository to the CentOS 7.8.2003 vault, so yum keeps working against the frozen 7.8 package set:

yum repolist enabled
grep '^baseurl' /etc/yum.repos.d/CentOS-Base.repo
sudo yum check-update; echo "check-update exit: $?"

Expected output (every repository points at the 7.8.2003 vault, and check-update exits 0 because the image is already patched to the last 7.8 vault packages):

repo id                    repo name                                      status
base/x86_64                CentOS-7.8.2003 - Base (vault)                 10,070
extras/x86_64              CentOS-7.8.2003 - Extras (vault)                  413
updates/x86_64             CentOS-7.8.2003 - Updates (vault)               1,134
repolist: 11,617
baseurl=https://vault.centos.org/7.8.2003/os/$basearch/
baseurl=https://vault.centos.org/7.8.2003/updates/$basearch/
baseurl=https://vault.centos.org/7.8.2003/extras/$basearch/
baseurl=https://vault.centos.org/7.8.2003/centosplus/$basearch/
check-update exit: 0

check-update returning 0 means no newer packages exist in the 7.8 vault — the image is patched to the end of that package set. No further security updates will ever be published upstream, for 7.8 or for any other CentOS 7 release. There is no unattended update timer armed on this image, because there is nothing left for it to fetch.

Those baseurl lines are also the pin. They name 7.8.2003 literally rather than $releasever, which is what stops yum update from walking the machine onto 7.9. If you deliberately want to move to the last CentOS 7 package set, edit /etc/yum.repos.d/CentOS-Base.repo and replace 7.8.2003 with 7.9.2009 throughout, then run sudo yum clean all && sudo yum update. Do that only if you no longer need the 7.8 platform, because it cannot be undone by another yum update.

Terminal showing yum repolist with the base updates and extras repositories pinned to the CentOS 7.8.2003 vault totalling 11,617 packages, the CentOS-Base.repo baseurls at vault.centos.org 7.8.2003, yum check-update exiting 0 meaning patched to the final 7.8 vault packages, and exactly one installed kernel package

Step 7: Verify the security posture

Confirm SELinux is enforcing, root is locked, SSH is key only, and nothing but SSH is listening off the machine:

sudo getenforce
sudo passwd -S root
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|pubkeyauthentication)'
sudo ss -tlnp

Expected output:

Enforcing
root LK 2009-12-22 -1 -1 -1 -1 (Alternate authentication scheme in use.)
permitrootlogin no
pubkeyauthentication yes
passwordauthentication no
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port
LISTEN     0      128          *:22                       *:*                   users:(("sshd",pid=1391,fd=3))
LISTEN     0      100    127.0.0.1:25                       *:*                   users:(("master",pid=1249,fd=13))
LISTEN     0      128       [::]:22                    [::]:*                   users:(("sshd",pid=1391,fd=4))
LISTEN     0      100      [::1]:25                    [::]:*                   users:(("master",pid=1249,fd=14))

LK is the field that matters: the root password is locked, so there is no password anyone could log in with. The trailing "Alternate authentication scheme in use" is expected on any Azure-provisioned Linux machine: cloud-init has placed your public key in /root/.ssh/authorized_keys behind a command="..." restriction that only ever prints "Please login as the user azureuser rather than the user root". That entry is your own key, not a cloudimg one, and PermitRootLogin no refuses the connection before it is ever consulted — an ssh root@<vm-ip> attempt returns Permission denied (publickey).

Read the Local Address column, not the peer column. The only address reachable from off the machine is *:22. Postfix on port 25 is bound to loopback only (127.0.0.1 and [::1]), so it is not exposed.

rpcbind — which binds 0.0.0.0:111 on a stock CentOS 7 — is not installed on this image at all, and its socket unit is masked in addition, so that a later yum install nfs-utils cannot bring the port back without you noticing. Confirm both facts for yourself:

rpm -q rpcbind nfs-utils || echo "neither package is installed"
sudo systemctl is-enabled rpcbind.socket 2>&1 || true

Terminal showing getenforce reporting Enforcing with the targeted policy in enforcing mode, passwd -S root reporting root as LK meaning password locked, the effective sshd policy reporting permitrootlogin no pubkeyauthentication yes and passwordauthentication no, rpcbind and nfs-utils both absent with the socket masked, ss showing SSH on port 22 as the only listener reachable off the machine, and free reporting zero swap

Step 8: Verify Azure integration

Confirm 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
free -h

Expected output:

active
enabled
/usr/bin/cloud-init 18.5
active
              total        used        free      shared  buff/cache   available
Mem:           3.9G        192M        3.3G         16M        338M        3.4G
Swap:            0B          0B          0B

waagent is what lets Azure provision your SSH key, resize the OS disk, run extensions and report VM health, so it should always be active and enabled. On CentOS 7.8 it is the python2 build of the agent, WALinuxAgent 2.2.38, which is the newest build the 7.8 extras vault published — that is the correct version for this point release, not a stale one.

Swap: 0B is deliberate. Azure manages swap on the temporary resource disk through waagent, and no swap file or swap partition ships inside the image.

Step 9: Networking and the firewall

The Azure Network Security Group is the control plane for inbound and outbound traffic, and it is the first and usually the only place you need to open a port. The image advertises a single inbound port, SSH on 22.

A host firewall runs as well. firewalld is active with only the SSH service allowed:

sudo firewall-cmd --state
sudo firewall-cmd --list-services

Expected output:

running
dhcpv6-client ssh

To open another service, add it and reload:

sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

If you need NFSv3, install the NFS tooling and unmask the RPC helper. Both steps are required: the packages are absent, and the socket unit is masked so it cannot start on its own even once they are installed.

sudo yum install -y nfs-utils
sudo systemctl unmask rpcbind.socket
sudo systemctl enable --now rpcbind.socket

Opening port 111 to the network also needs a firewalld service and an NSG rule. NFSv4 does not use rpcbind at all, so most NFS deployments never need this.

Step 10: Install software

The base, updates and extras repositories are enabled and pinned to the 7.8 vault. Search and install as normal, remembering that nothing newer than the 7.8.2003 package set is available:

yum search httpd
sudo yum install -y httpd
sudo systemctl enable --now httpd

Only what CentOS 7.8 itself shipped is available, which is a smaller set than the terminal 7.9 release: 11,617 packages here against roughly 16,700 in 7.9.2009. Popular packages that live in EPEL rather than the base distribution — nginx is the usual surprise — are not in these repositories and yum install nginx will report no match. Anything newer than 2020, or EPEL-only, has to come from a third party repository (EPEL's own CentOS 7 archive, a vendor repository, or a source build), because the CentOS 7 repositories are frozen.

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.

Common Use Cases

  • Running software whose support statement names CentOS or RHEL 7.8 specifically
  • Reproducing or debugging a legacy estate that is still standardised on the 7.8 point release
  • Lift and shift of an existing CentOS 7.8 estate into Azure as a migration step
  • Compatibility and RPM validation work against the RHEL 7.8 ABI
  • Building or testing packages that must link against the 7.8 library set rather than 7.9

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 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 actually offering, run ssh -v azureuser@<vm-ip> from your workstation and look for the Offering public key lines.

growpart says NOCHANGE

The partition already fills the disk, so there is nothing to claim — which on this image is the normal state, because cloud-init grew root at boot. growpart exits non zero on NOCHANGE by design. If root is genuinely smaller than the disk, stop the VM, raise the OS disk size in Azure and start it again; the grow happens automatically on the way back up (Step 5).

The release says 7.9, not 7.8

Something has moved the machine off the pin, which almost always means a repository file was edited or a third party .repo was added that points at $releasever or at 7.9.2009. Check what the repositories actually resolve to:

yum repolist enabled
grep -REn '^[^#]*baseurl' /etc/yum.repos.d/ | grep -v 7.8.2003 || echo "no active baseurl outside 7.8.2003"

The first command is the one that decides the question: every repository yum will actually read must be one of the three CentOS-7.8.2003 entries. The second lists any baseurl line, in any file, that is not on the 7.8 vault — grep for lines that are not commented out, or the explanatory comments in the shipped files show up as false hits.

On an unmodified image the second command still returns a handful of lines, and that is expected: CentOS-Sources, CentOS-Debuginfo, CentOS-Media, CentOS-Vault and CentOS-CR are the stock repository definitions CentOS 7 has always shipped, left exactly as upstream published them, and every one of them is enabled=0. They are inert while disabled. Be aware, though, that enabling one is a way to pull packages from outside 7.8 — CentOS-CR in particular carries packages staged for the next point release, so enabling it is the most direct way to break the pin.

A machine that has already been updated to 7.9 cannot be moved back to 7.8 by a package manager operation — redeploy from the image instead.

Package manager cannot reach a mirror

CentOS 7's original mirrors were retired at end-of-life. This image already points at the vault, but if you add a third party .repo that still references mirror.centos.org you will see 404s. Repoint it to https://vault.centos.org/7.8.2003/... or remove it. Confirm nothing still references the retired mirrors:

grep -REn '^[^#]*mirror\.centos\.org' /etc/yum.repos.d/ || echo "no active repo references the retired mirrors"

(The shipped .repo files mention mirror.centos.org in their comments, explaining why they were repointed, so grep for lines that are not commented out.)

Azure agent not running

sudo systemctl status waagent
sudo systemctl enable --now waagent

A service is blocked and the logs mention SELinux

SELinux is enforcing on this image. Rather than disabling it, look at what was denied:

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

Important Notes

CentOS Linux is free and open source. It is not covered by a single licence: it is a distribution assembled from thousands of independently packaged components, each carrying its own terms, including the GPL, LGPL, MIT, BSD, Apache 2.0 and MPL. Every package's terms are readable with rpm -qi <package> and under /usr/share/licenses/. No subscription, licence key or Red Hat entitlement is required. Pinning to a back catalogue point release adds no further licence obligation.

CentOS Linux 7 reached end-of-life on 30 June 2024 and receives no further upstream security updates. This image is patched only to its capture date, from the frozen CentOS 7.8.2003 vault, and is provided for legacy migration use. Plan a migration to a supported distribution (AlmaLinux, Rocky Linux, CentOS Stream, or a current RHEL) for any workload that must remain secure.

CentOS is a trademark of Red Hat, Inc. The name is used here nominatively, only to identify the distribution this image contains. cloudimg is not affiliated with, endorsed by or sponsored by Red Hat or the CentOS Project.

Support

For assistance with this image, contact cloudimg support: