Operating Systems Azure

CentOS 7.2 LVM on Azure User Guide

| Product: CentOS 7.2 LVM on Azure

Overview

This guide covers the deployment and configuration of CentOS 7.2 LVM (CentOS Linux 7.2.1511 with an LVM root) 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. Two things define this particular image:

  • It is pinned to the 7.2.1511 point release. Its package repositories point at the frozen CentOS 7.2.1511 vault, so a routine yum update applies the errata issued for 7.2 and does not roll the machine forward to 7.3.
  • Its root filesystem is an LVM logical volume, not a fixed partition, so you can grow it onto a larger disk or across a second disk while the machine is running.

The point release matters when an application, a kernel module, a driver or a vendor support statement is certified against one specific CentOS 7 point release rather than the CentOS 7 series as a whole. The LVM layout matters when storage has to change shape after the machine is built. If you do not need the LVM root, use the CentOS 7.2 image, which ships the same point release on a plain single partition. If you do not need a specific point release, use CentOS 7 LVM, which ships 7.9.2009, the final CentOS 7 release, on the same layout.

End-of-life notice — read this first

CentOS Linux 7 reached end-of-life on 30 June 2024, and 7.2.1511 is a back-catalogue point release that was superseded upstream by 7.3 through 7.9. Both facts matter:

  • This image is patched to the last packages that exist for 7.2.1511, from the frozen CentOS 7.2.1511 vault (vault.centos.org). "Fully patched" here means patched to the end of that point release's own errata stream — the newest kernel it ever received is 3.10.0-327.36.3.el7.
  • Errata published after 7.2 closed were released against later point releases, not against 7.2. Staying on 7.2 means deliberately forgoing them.
  • CentOS 7 as a whole receives no further upstream security updates of any kind after its end-of-life date. Over time this 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 and version-pinned use — running software certified only against CentOS 7.2, or reproducing an environment at the exact release it was signed off on. 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 the upstream mirror service, which was retired at end-of-life. This image has already repointed every repository to the CentOS 7.2.1511 vault, so yum keeps working — against the frozen 7.2 package set — out of the box.

One package on this image is not from 7.2 — the Azure provisioning agent

This is specific to CentOS 7.0, 7.1 and 7.2, and it is disclosed here because it is a real deviation from an otherwise exact point release pin.

CentOS 7.2.1511 never shipped a WALinuxAgent package. The Azure Linux Agent first appears in the CentOS 7.3.1611 repositories. The 7.2.1511 vault contains no copy of it in any repository — not in os, updates, extras or centosplus. The cloud-init that 7.2 does ship (version 0.7.5, from 2014) cannot stand in for it: its Azure support delegates the agent step to a walinuxagent service that would not exist, and its parser reads only the older fingerprint form of the SSH key, not the inline value form Azure sends today.

Without a provisioning agent an Azure virtual machine cannot receive the SSH key you supply at create time or report itself ready to the platform, so a strictly-7.2-only image could not be deployed at all.

So this image is CentOS Linux 7.2.1511 in full, with exactly one exception: WALinuxAgent-2.2.0-4.el7.noarch, taken from the CentOS 7.3.1611 snapshot and pinned by URL and SHA-256 checksum. That package is a noarch build tagged for the generic el7 platform rather than for 7.3 specifically, and every dependency it declares is satisfied from 7.2.1511 itself — so it is the only package on the system that does not come from the 7.2 vault. One of those dependencies is NetworkManager, which is therefore installed on this image but left disabled, with the legacy network service owning eth0. The build refuses to complete if a second out of pin package ever appears.

The image states this on disk so you can confirm it yourself rather than taking our word for it:

cat /usr/share/doc/cloudimg/out-of-pin-packages.txt

Expected output:

cloudimg — CentOS 7.2 LVM (CentOS Linux 7.2.1511, root on an LVM logical volume) Azure image

This image is CentOS Linux 7.2.1511 from the frozen vault.centos.org/7.2.1511
tree, with EXACTLY ONE exception: the Azure provisioning agent.

CentOS 7.2.1511 never shipped a WALinuxAgent package — it first appears in
CentOS 7.3.1611 — and without a provisioning agent an Azure VM cannot receive
your SSH key or report ready to the platform. The agent below is therefore
sourced from the CentOS 7.3.1611 snapshot, pinned by URL and sha256:

  package = WALinuxAgent-2.2.0-4.el7.noarch
  source  = https://vault.centos.org/7.3.1611/extras/x86_64/Packages/WALinuxAgent-2.2.0-4.el7.noarch.rpm
  sha256  = 91e1847c85fb2d06b2443bbea704f1deb9a6e639c7c9f3d1eefdb8d9aaf1f6cf

Every other package on this system resolves from vault.centos.org/7.2.1511.
Verify it yourself:
  repoquery -a --qf '%{name}-%{version}-%{release}.%{arch}' | sort -u > /tmp/inpin
  rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | grep -v ^gpg-pubkey- | sort -u > /tmp/inst
  comm -23 /tmp/inst /tmp/inpin

generated at build time: 2026-09-11T01:29:44Z

And you can reproduce the whole comparison. This lists every installed package that is not available from the repositories this image is pinned to:

repoquery -a --qf '%{name}-%{version}-%{release}.%{arch}' 2>/dev/null | sort -u > /tmp/inpin
rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | grep -v '^gpg-pubkey-' | sort -u > /tmp/inst
comm -23 /tmp/inst /tmp/inpin

Expected output — one line, the agent, and nothing else:

WALinuxAgent-2.2.0-4.el7.noarch

If an exact, unmodified 7.2.1511 package set matters more to you than deployability on Azure, the CentOS 7 LVM image (7.9.2009) or the CentOS 7.6 LVM image are pinned point releases on the same LVM layout whose own vault trees do include the Azure agent, so they carry no out of pin package at all.

What's included

  • CentOS Linux 7.2.1511 (Core), binary compatible with RHEL 7
  • Root on an LVM logical volume/dev/mapper/centos-root in volume group centos — with /boot on a plain xfs partition
  • Repositories pinned to vault.centos.org/7.2.1511, so yum keeps working post-EOL and stays on 7.2
  • Every package that exists for 7.2.1511 applied at build time, including kernel 3.10.0-327.36.3.el7
  • growpart, pvresize, lvextend and xfs_growfs preinstalled, so the root volume grows online
  • Azure Linux Agent (WALinuxAgent 2.2.0-4.el7 — the ONE package not from the 7.2.1511 vault; see "One package is not from 7.2" below) enabled, handling provisioning, SSH key injection and host key regeneration
  • Chronyd for NTP time synchronisation
  • SELinux in enforcing mode
  • firewalld enabled in the default public zone, allowing only SSH
  • Gen1 Hyper V virtual machine support (BIOS boot)
  • 24/7 cloudimg support

Platform: Microsoft Azure (Gen1 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.
  • PermitRootLogin is set to no in the main /etc/ssh/sshd_config. CentOS 7's sshd has no sshd_config.d include directory, so the setting is applied in the main file, not a drop-in.
  • 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.
  • SELinux is left in enforcing mode, the CentOS default.
  • The only externally reachable listener is SSH on port 22. rpcbind is not installed at all, and its socket unit is masked so a later package install cannot silently reopen port 111.
  • firewalld ships enabled and running in the default public zone, allowing only the ssh service, so the host enforces the same single-port posture the Network Security Group does. See Step 9 before opening a new port — it has to be opened in both places.

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.

Step 1: Deploy the Virtual Machine

Option A: Azure Portal

  1. Navigate to the Azure Marketplace and search for "CentOS 7.2 LVM 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 Inbound Port Rules, allow SSH (port 22)
  11. Under Disks, set the OS disk size you want. The image ships a 10 GB disk; asking for more here gives you unallocated space that Step 5 turns into root capacity without a rebuild
  12. Click Review + Create, then Create

Option B: Azure CLI

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

--os-disk-size-gb 32 is optional. It is shown because it is what makes Step 5 worth running on a brand new machine: the image's own layout is 10 GB, so a larger OS disk arrives with unallocated space at the end of the disk that you then claim into the root volume.

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-72-lvm-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.

Non-interactive sudo works on this image. Stock CentOS 7.2 still carries Defaults requiretty in /etc/sudoers, which Red Hat removed in 7.3 — it makes ssh <host> 'sudo <command>' fail with "sorry, you must have a tty to run sudo" and breaks most remote automation. cloudimg negates it with /etc/sudoers.d/90-cloudimg-cloud, so this image behaves the same way every CentOS 7.3+ image in the family does. Note also that ss, getenforce and sshd live in /usr/sbin, which CentOS 7 adds to a non-root PATH only via /etc/profile — a file a non-interactive ssh <host> '<command>' never reads. That is why the commands below are written with sudo in front.

Step 3: Confirm the point release

Check that the machine is the CentOS Linux 7.2.1511 release you expect. The centos-release package is the authoritative answer — /etc/os-release only carries the major version on 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.2.1511 (Core)
centos-release-7-2.1511.el7.centos.2.10.x86_64
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
VERSION_ID="7"
3.10.0-327.36.3.el7.x86_64 x86_64

VERSION_ID="7" is expected: CentOS 7's /etc/os-release records only the major version, which is why /etc/centos-release and rpm -q centos-release are the checks that actually confirm the point release. Kernel 3.10.0-327.36.3.el7 is the newest kernel ever published for 7.2.1511. (CentOS 7's /etc/os-release has no PLATFORM_ID field — that was introduced in the el8 line.)

rpm -q centos-release is the rpm-level proof of the point release, so a hand-edited /etc/centos-release cannot fake it. On 7.2 the updates repository ships no centos-release package at all, so this NEVRA is the one the install tree laid down and yum update never touches it.

Terminal showing cat of etc centos-release reporting CentOS Linux release 7.2.1511 Core, rpm -q centos-release reporting centos-release-7-2.1511.el7.centos.2.10, os-release fields ID centos and VERSION_ID 7, and uname reporting the 3.10.0-327.36.3.el7 kernel on x86_64

Step 4: Verify the LVM root layout

This is the defining feature of this image, and the reason to choose it over the standard CentOS 7.2 listing. The root filesystem is a logical volume, not a plain partition.

First, the block layout:

lsblk -o NAME,TYPE,MOUNTPOINT,SIZE,FSTYPE

Expected output on a machine launched with the default 10 GB OS disk:

NAME            TYPE MOUNTPOINT  SIZE FSTYPE
fd0             disk               4K
sda             disk              10G
├─sda1          part /boot         1G xfs
└─sda2          part               9G LVM2_member
  └─centos-root lvm  /             9G xfs
sdb             disk               8G
└─sdb1          part               8G ntfs
sr0             rom              630K

The lvm in the TYPE column against / is the proof that this is the LVM variant. /dev/sda2 is flagged LVM2_member, not a filesystem — it is the physical volume. sdb is the Azure temporary resource disk, which every Azure VM gets; this image deliberately leaves it alone rather than formatting and mounting it, so it appears with whatever filesystem the platform put there and is not part of the volume group. Mount it yourself if you want scratch space, remembering that Azure does not preserve its contents across a deallocation.

Now confirm the LVM objects themselves:

findmnt /
findmnt /boot
sudo vgs
sudo lvs
sudo pvs

Expected output:

TARGET SOURCE                  FSTYPE OPTIONS
/      /dev/mapper/centos-root xfs    rw,relatime,seclabel,attr2,inode64,noquota
TARGET SOURCE    FSTYPE OPTIONS
/boot  /dev/sda1 xfs    rw,relatime,seclabel,attr2,inode64,noquota
  VG     #PV #LV #SN Attr   VSize VFree
  centos   1   1   0 wz--n- 9.00g    0
  LV   VG     Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root centos -wi-ao---- 9.00g
  PV         VG     Fmt  Attr PSize PFree
  /dev/sda2  centos lvm2 a--  9.00g    0

Root is /dev/mapper/centos-root: logical volume root inside volume group centos, on physical volume /dev/sda2. /boot deliberately stays a plain xfs partition, because grub2 on CentOS 7 reads the kernel and initramfs from it before LVM is available. VFree 0 and PFree 0 are correct on a default 10 GB machine — the volume group already owns everything the disk has to give, which is exactly the state Step 5 changes.

vgs, lvs and pvs live in /usr/sbin, which CentOS 7 adds to a non-root PATH only from /etc/profile. An interactive login shell has them; a one-shot ssh host 'vgs' does not. Running them through sudo, as above, works in both cases.

Terminal showing lsblk with root on the LVM logical volume centos-root over the LVM2_member partition sda2, findmnt confirming root is dev mapper centos-root and boot is the plain partition dev sda1, and vgs lvs pvs showing the centos volume group, the root logical volume and the dev sda2 physical volume

Step 5: Grow the root filesystem online

This is what the LVM layout buys you: root grows while the machine is running, with no repartitioning, no reboot and no downtime.

Give the VM a larger OS disk first. If you did not size it up at create time, stop the VM, raise the OS disk size in the Azure Portal (or with az disk update --size-gb), and start it again. The new space arrives as unallocated room at the end of /dev/sda.

Then grow the partition, the physical volume, the logical volume and the filesystem, in that order, and confirm the volume group has no unclaimed space left:

sudo growpart /dev/sda 2
sudo pvresize /dev/sda2
sudo lvextend -l +100%FREE /dev/centos/root
sudo xfs_growfs /
df -h /
FREE=$(sudo vgs --noheadings -o vg_free_count centos | tr -dc '0-9')
PVB=$(sudo pvs --noheadings --units b --nosuffix -o pv_size /dev/sda2 | tr -dc '0-9')
PARTB=$(( $(cat /sys/class/block/sda2/size) * 512 ))
if [ "${FREE:-1}" -ne 0 ]; then echo "FAIL: ${FREE} free extents remain in VG centos"; exit 1; fi
if [ "$(( PARTB - PVB ))" -gt 8388608 ]; then echo "FAIL: pvresize did not take - partition ${PARTB}B vs physical volume ${PVB}B"; exit 1; fi
echo "root volume fully extended: 0 free extents in VG centos, and the physical volume fills the partition"

Expected output, growing a 9 GB root onto a 32 GB OS disk:

CHANGED: partition=2 start=2099200 old: size=18872320 end=20971520 new: size=65004305,end=67103505
  Physical volume "/dev/sda2" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized
  Size of logical volume centos/root changed from 9.00 GiB (2303 extents) to 30.99 GiB (7934 extents).
  Logical volume root successfully resized.
data blocks changed from 2358272 to 8124416
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   31G  849M   31G   3% /
root volume fully extended: 0 free extents in VG centos, and the physical volume fills the partition

The filesystem went from 9 GB to 31 GB while it was mounted and serving. Nothing was unmounted and the machine was never rebooted — last reboot still shows the single boot the machine started with. (xfs_growfs also prints the filesystem geometry above the data blocks changed line; that is normal and is omitted here for brevity. The Used figure will differ on your machine.)

The two checks at the end are what make the four commands honest, and they are deliberately a pair. growpart reports NOCHANGE and exits non zero when the partition already fills the disk, and lvextend exits non zero when there are no free extents to claim — both of which are the correct answer on a machine already at full size, not errors — so the block cannot simply trust its exit codes.

  • Zero free extents in the volume group is the same answer, 0, whether you just grew the volume or it was already at maximum, and a different answer if lvextend silently failed.
  • The physical volume still fills its partition is the check that catches a failed pvresize, which the extent count alone cannot: if the partition grows and the physical volume does not, the volume group never gains the space, so there are no free extents to find and the first check would report success on a grow that never happened. The 8 MiB tolerance covers LVM's metadata area and extent rounding; on a healthy machine the gap is a few MiB, while a skipped pvresize on a 32 GB disk leaves a gap of tens of gigabytes.

Adding a second disk to the volume group

The other reason to run an LVM root is that you can pool a brand new disk under the existing filesystem instead of mounting it somewhere else. Attach a data disk to the VM in Azure, find its device name, then:

sudo pvcreate /dev/sdc
sudo vgextend centos /dev/sdc
sudo lvextend -l +100%FREE /dev/centos/root
sudo xfs_growfs /

Root now spans both disks. On a plain partition layout — which is what the CentOS 7.2 image ships — neither of these operations is possible without rebuilding the machine.

Step 6: The point release pin and the vault update path

Because CentOS 7 is end-of-life its original mirrors are gone, so every repository is repointed to the CentOS 7.2.1511 vault — and pinning to that particular vault tree is what keeps the machine on 7.2:

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

Expected output. Every repository resolves to vault.centos.org/7.2.1511, and check-update exits 0 because the image is already patched to the last packages published for this point release:

repo id                    repo name                                      status
base/x86_64                CentOS-7.2.1511 - Base (vault)                  9,007
extras/x86_64              CentOS-7.2.1511 - Extras (vault)                  393
updates/x86_64             CentOS-7.2.1511 - Updates (vault)               2,560
repolist: 11,960
baseurl=https://vault.centos.org/7.2.1511/os/$basearch/
baseurl=https://vault.centos.org/7.2.1511/updates/$basearch/
baseurl=https://vault.centos.org/7.2.1511/extras/$basearch/
baseurl=https://vault.centos.org/7.2.1511/centosplus/$basearch/
check-update exit: 0

Why the pin holds. A vault tree for a point release is frozen and self contained. The updates repository for 7.2.1511 carries the errata issued during 7.2's own lifetime — the kernel runs up to 3.10.0-327.36.3.el7 — and it contains no centos-release package, so nothing in this tree can rewrite the release string. yum update applies those errata and stops. There is no package here that can move the machine to 7.3 or beyond.

CentOS also ships a CentOS-Vault.repo listing every historical point release. On this image every one of those sections is left disabled, so nothing crosses point releases unless you deliberately enable it:

awk '/^enabled=1/{n++} END{print n+0}' /etc/yum.repos.d/CentOS-Vault.repo

Expected output:

0

check-update returning 0 means no newer packages exist in the 7.2.1511 vault — the image is patched to the end of this point release's errata stream. No further security updates will ever be published upstream, for 7.2 or for CentOS 7 at all. For anything beyond legacy migration or version pinning, move to a supported distribution.

Terminal showing the CentOS-Base.repo baseurls pinned to vault.centos.org 7.2.1511, yum check-update exiting 0 meaning patched to the last packages published for this point release, the shipped cloudimg disclosure naming WALinuxAgent 2.2.0-4.el7.noarch with its CentOS 7.3.1611 source URL and sha256, and a live comparison of every installed package against the pinned repositories returning that single package and nothing else

Step 7: Verify the security posture

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

sudo getenforce
sudo passwd -S root
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|pubkeyauthentication) '
systemctl is-active rpcbind.socket || true

Expected output:

Enforcing
root LK 2009-12-22 -1 -1 -1 -1 (Alternate authentication scheme in use.)
permitrootlogin no
pubkeyauthentication yes
passwordauthentication no
unknown

root LK means the root password is locked. rpcbind.socket reporting unknown is intentional and is stronger than inactive: the rpcbind package is not installed on this image at all, so there is no RPC listener on port 111 to disable. If you need NFSv3 later, install nfs-utils first, then sudo systemctl unmask rpcbind.socket && sudo systemctl enable --now rpcbind.socket.

getenforce, sshd and ss live in /usr/sbin, which CentOS 7 adds to a non-root PATH only from /etc/profile. An interactive login shell has them; a one-shot ssh host 'getenforce' does not. Running them through sudo (as above) works in both cases.

Terminal showing getenforce reporting Enforcing, passwd -S root reporting root as LK meaning locked, the effective sshd policy reporting permitrootlogin no passwordauthentication no and pubkeyauthentication yes, rpcbind neither installed nor enabled, only port 22 listening off box, and no swap in the image

Step 8: Verify Azure integration

Confirm the Azure Linux Agent and time synchronisation are healthy, and check your resources:

systemctl is-active waagent
systemctl is-enabled waagent
rpm -q WALinuxAgent
grep -E '^Provisioning\.(Agent|Enabled|UseCloudInit)=' /etc/waagent.conf
systemctl is-active chronyd
df -h /
free -h

Expected output on a default 10 GB machine:

active
enabled
WALinuxAgent-2.2.0-4.el7.noarch
Provisioning.Enabled=y
Provisioning.Agent=waagent
Provisioning.UseCloudInit=n
active
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root  9.0G  940M  8.1G  11% /
              total        used        free      shared  buff/cache   available
Mem:           3.9G        170M        3.5G         16M        242M        3.5G
Swap:            0B          0B          0B

waagent is what lets Azure provision your SSH key, run extensions and report VM health, so it should always be active and enabled. The version here is 2.2.0-4.el7 rather than a 7.2 build, because 7.2.1511 never shipped the agent at all — see "One package on this image is not from 7.2" above. Provisioning.Agent and Provisioning.UseCloudInit are inert at this agent version (they arrive in later releases); they are written for consistency with the rest of cloudimg's CentOS 7 range, and Provisioning.Enabled=y is the key this agent actually reads.

On this image the Azure Linux Agent is the sole provisioning agent and cloud-init is not installed. That is deliberate, and on this point release the reason is specific: the cloud-init that CentOS 7.2.1511 ships (0.7.5) cannot provision an Azure VM. Its Azure data source shells out to the Azure Linux Agent for the agent step, and its key parser only understands the older fingerprint form — it silently discards the inline public key Azure sends today, so a machine relying on it would come up with an empty authorized_keys. Exactly one of the two has to own provisioning, and on this image that is the agent. It handles injecting the SSH key you supply at create time, regenerating the SSH host keys, setting the hostname and reporting VM health. Leaving cloud-init out is what makes the image provision reliably and receive your key on first boot.

If your workflow depends on cloud-init specifically — #cloud-config user data, for example — this is not the image for it; use a CentOS Stream, AlmaLinux or Rocky Linux image instead. Custom data supplied to the VM is still delivered to /var/lib/waagent/CustomData, so a first-boot script of your own can read it there.

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

Step 9: Networking — there are TWO firewalls

This image runs a host firewall as well as the Azure Network Security Group, and a new port has to be opened in both. firewalld ships installed, enabled and active, exactly as it does on a stock CentOS 7 install:

sudo ss -tlnp
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --list-all

Expected output. The only externally reachable listener is sshd on port 22 — you will also see postfix bound to 127.0.0.1:25 and ::1:25, which is the local mail transport, reachable only from the machine itself and not from the network. The process IDs will differ on your machine:

State      Recv-Q Send-Q Local Address:Port               Peer Address:Port
LISTEN     0      128          *:22                       *:*                   users:(("sshd",pid=1257,fd=3))
LISTEN     0      100    127.0.0.1:25                       *:*                   users:(("master",pid=1360,fd=13))
LISTEN     0      128         :::22                      :::*                   users:(("sshd",pid=1257,fd=4))
LISTEN     0      100        ::1:25                      :::*                   users:(("master",pid=1360,fd=14))
public
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

Read the Local Address:Port column, not the peer column — that is what tells you what the machine is actually offering to the network.

Two CentOS 7.2 formatting notes, because they differ from later point releases and from most documentation. The iproute package here is 3.10, which prints the IPv4 wildcard as *:22 (not 0.0.0.0:22) and the IPv6 addresses unbracketed:::22 and ::1:25, where CentOS 7.7 and later print [::]:22 and [::1]:25. And this firewalld prints a shorter --list-all than later releases: no target:, icmp-block-inversion:, protocols: or source-ports: lines. Both are cosmetic, but they are worth knowing before you write a script that parses either.

One command to avoid on this release: ss -H (--no-header). That option arrives in iproute2 4.x, and on CentOS 7.2's ss it is not merely rejected — it prints the usage message to standard output and exits 0, so a script that filters ss -H -tln gets a parseable-looking result with no listeners in it and no error to notice. Use plain ss -tln and drop the header yourself with awk '$1=="LISTEN"'.

The practical consequence is for every port you add afterwards. Opening 443 in the NSG alone is not enough: the traffic reaches the machine and firewalld drops it, which looks exactly like a broken application. Open it in both places — in the Azure NSG as an inbound rule, and on the machine with sudo firewall-cmd --permanent --add-service=https followed by sudo firewall-cmd --reload. For a port with no named service, use sudo firewall-cmd --permanent --add-port=8080/tcp and the same reload. Check the result with sudo firewall-cmd --list-all again, and always keep the ssh service in the zone so you do not lock yourself out. If you would rather manage inbound access solely with the NSG, sudo systemctl disable --now firewalld removes the host layer, but do that deliberately rather than by accident.

Common Use Cases

  • Lift-and-shift of a CentOS 7 estate whose machines already use an LVM root, so the storage layout matches what the applications and runbooks expect
  • Running software certified specifically against CentOS 7.2, rather than against the CentOS 7 series
  • Workloads whose root volume has to grow, or spread across additional disks, without rebuilding the machine
  • Compatibility and RPM validation work against the RHEL 7.2 ABI

For any workload that must stay secure long term, migrate to AlmaLinux, Rocky Linux, CentOS Stream, or a current RHEL — CentOS 7 receives no further upstream security updates.

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.

growpart says NOCHANGE

NOCHANGE: partition 2 could only be grown by -6695 [fudge=20480] means /dev/sda2 already extends to the end of the disk — there is no unallocated space to claim, and growpart exits non zero to say so. Raise the OS disk size first (stop the VM, change the size, start it again), then re-run Step 5.

lvextend says the new size matches the existing size

New size (2303 extents) matches existing size (2303 extents) means the volume group has no free extents, so there is nothing to add to the logical volume. Check with sudo vgs: if VFree is 0, either grow the physical volume first (Step 5) or add a second disk to the group.

Package manager cannot reach a mirror

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

grep -RE '^[[:space:]]*(baseurl|mirrorlist)[[:space:]]*=.*mirror(list)?\.centos\.org' /etc/yum.repos.d/ \
  || echo "no active repository references the retired mirrors"

Expected output:

no active repository references the retired mirrors

Match only uncommented baseurl= / mirrorlist= lines, as above. A plain grep -R mirror.centos.org also matches commented-out stock lines and the explanatory comment cloudimg writes into CentOS-Base.repo, so it reports hits on a perfectly correct image.

A package I need is not in the repositories

The 7.2.1511 vault is frozen, and it is smaller than the final 7.9 tree — anything added to CentOS 7 after 7.2 closed is not in it. EPEL-only packages (for example nginx) are not present in base, updates or extras at all. Either install from an external repository you control, or use the CentOS 7 LVM image, which ships the final 7.9.2009 package set on the same LVM layout.

Note that enabling one of the other point release sections in /etc/yum.repos.d/CentOS-Vault.repo will pull packages from a different release and defeat the point release pin this image exists to provide.

A service is blocked and the logs mention SELinux

SELinux ships enforcing. If a service you install is denied access to a path or port, the right fix is a policy adjustment (semanage fcontext, semanage port, or an audit2allow module built from the denial), not disabling SELinux. sudo ausearch -m avc -ts recent shows the denials.

Azure agent not running

Check the agent's status:

systemctl status waagent --no-pager

If it is not running, start and enable it with sudo systemctl enable --now waagent.

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, and neither the point release pin nor the LVM layout adds any further obligation.

CentOS Linux 7 reached end-of-life on 30 June 2024 and receives no further upstream security updates, and 7.2.1511 was superseded upstream by 7.3 through 7.9. This image is patched to the last packages that exist for 7.2.1511, from the frozen CentOS 7.2.1511 vault, and is provided for legacy-migration and version-pinned 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 never published an LVM cloud image for any CentOS 7 release. cloudimg builds this layout from an unattended installation of the frozen 7.2.1511 vault tree, so the release the machine reports is a fact of how it was made rather than an artefact of a chosen file name, and the online extension in Step 5 is proven on a fresh machine before the image is published.

This image contains exactly one package that is not from the 7.2.1511 vault: the Azure provisioning agent WALinuxAgent-2.2.0-4.el7.noarch, taken from the CentOS 7.3.1611 snapshot and pinned by URL and SHA-256 (91e1847c85fb2d06b2443bbea704f1deb9a6e639c7c9f3d1eefdb8d9aaf1f6cf), because CentOS 7.2.1511 never shipped one and an Azure VM cannot be provisioned without it. It is recorded on the image at /usr/share/doc/cloudimg/out-of-pin-packages.txt and the build fails closed if a second such package ever appears. See "One package on this image is not from 7.2" above.

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.

Support

For assistance with this image, contact cloudimg support: