<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SRE Archives - Linuxcent</title>
	<atom:link href="https://linuxcent.com/category/sre/feed/" rel="self" type="application/rss+xml" />
	<link>https://linuxcent.com/category/sre/</link>
	<description>Infrastructure security, from the kernel up.</description>
	<lastBuildDate>Sun, 22 Mar 2026 18:03:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.4</generator>

<image>
	<url>https://linuxcent.com/wp-content/uploads/2026/04/favicon-512x512-1-150x150.png</url>
	<title>SRE Archives - Linuxcent</title>
	<link>https://linuxcent.com/category/sre/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">211632295</site>	<item>
		<title>Cloud AMI Security Risks &#038; How Custom OS Images Fix them and what&#8217;s wrong with defaults</title>
		<link>https://linuxcent.com/cloud-ami-security-risks-custom-os-images/</link>
					<comments>https://linuxcent.com/cloud-ami-security-risks-custom-os-images/#respond</comments>
		
		<dc:creator><![CDATA[Vamshi Krishna Santhapuri]]></dc:creator>
		<pubDate>Sun, 15 Mar 2026 18:21:53 +0000</pubDate>
				<category><![CDATA[Linux Tutorials]]></category>
		<category><![CDATA[SRE]]></category>
		<category><![CDATA[ami]]></category>
		<category><![CDATA[cis-benchmark]]></category>
		<category><![CDATA[cloud-hardening]]></category>
		<category><![CDATA[custom-os-image]]></category>
		<category><![CDATA[image-hardening]]></category>
		<category><![CDATA[linux-security]]></category>
		<category><![CDATA[os-image]]></category>
		<category><![CDATA[os-image-builder-series]]></category>
		<category><![CDATA[rhel]]></category>
		<category><![CDATA[server-hardening]]></category>
		<category><![CDATA[ubuntu]]></category>
		<guid isPermaLink="false">https://linuxcent.com/?p=1421</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">minutes</span></span>~2,800 words &#160;·&#160; Reading time: 12 min &#160;·&#160; Series: OS Image Security, Post 1 of 6 When you launch an EC2 instance from an AWS Marketplace AMI, or spin up a VM from a cloud-provider base image on GCP or Azure, you&#8217;re trusting a decision someone else made months ago about what your server should ... <a title="Cloud AMI Security Risks &#038; How Custom OS Images Fix them and what&#8217;s wrong with defaults" class="read-more" href="https://linuxcent.com/cloud-ami-security-risks-custom-os-images/" aria-label="Read more about Cloud AMI Security Risks &#038; How Custom OS Images Fix them and what&#8217;s wrong with defaults">Read more</a></p>
<p>The post <a href="https://linuxcent.com/cloud-ami-security-risks-custom-os-images/">Cloud AMI Security Risks &#038; How Custom OS Images Fix them and what&#8217;s wrong with defaults</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">minutes</span></span><p><!-- ============================================================
     LINUXCENT.COM — PUBLISH-READY POST HTML
     Title : The anatomy of a production OS image — what's wrong
             with cloud defaults
     Series: OS Image Builder · Post 01 of 06
     ============================================================ --></p>
<p><em>~2,800 words &nbsp;·&nbsp; Reading time: 12 min &nbsp;·&nbsp; Series: OS Image Security, Post 1 of 6</em></p>
<p><!-- ── INTRO ──────────────────────────────────────────────── --></p>
<p>When you launch an EC2 instance from an AWS Marketplace AMI, or spin up a VM from a cloud-provider base image on GCP or Azure, you&#8217;re trusting a decision someone else made months ago about what your server should contain. That decision was made for the widest possible audience — not for your workload, your threat model, or your compliance requirements.</p>
<p>This post tears open what&#8217;s actually inside a default cloud image, compares it against what a production-hardened image should contain, and explains why the calculus changes depending on whether you&#8217;re deploying to AWS, an on-prem KVM host, or a Nutanix AHV cluster.</p>
<hr />
<p><!-- ── SECTION 1 ───────────────────────────────────────────── --></p>
<h2>What a cloud provider is actually optimising for</h2>
<p>AWS, Canonical, Red Hat, and every other publisher shipping to cloud marketplaces are solving a <strong>distribution problem</strong>, not a security problem. Their images need to:</p>
<ul>
<li>Boot successfully on any instance type in any region</li>
<li>Work for the first-time user running their first workload</li>
<li>Support every possible use case — web servers, databases, ML training jobs, bastion hosts, everything</li>
</ul>
<p>That constraint produces images that are, by design, <strong>permissive</strong>. Permissive gets out of the way. Permissive doesn&#8217;t break anything on day one. Permissive is also the opposite of what you want on a production server.</p>
<p>Let&#8217;s look at what &#8220;permissive&#8221; actually means in concrete terms.</p>
<hr />
<p><!-- ── SECTION 2 ───────────────────────────────────────────── --></p>
<h2>Dissecting a default AWS AMI</h2>
<p>Take Amazon Linux 2023 (AL2023), one of the more intentionally stripped-down cloud images available. Even with Amazon&#8217;s effort to reduce its footprint compared to AL2, a fresh AL2023 instance ships with more than most workloads need.</p>
<h3>Services running at boot that most workloads don&#8217;t need</h3>
<pre><code class="" data-line="">chronyd.service            # Fine — you need NTP
systemd-resolved.service   # Fine
dbus-broker.service        # Fine
amazon-ssm-agent.service   # Arguably fine if you use SSM
NetworkManager.service     # Debatable — most cloud workloads don&#039;t need NM
</code></pre>
<p>On a RHEL 8/9 or Ubuntu 22.04 Marketplace image, the list is longer. You&#8217;ll find <code class="" data-line="">avahi-daemon</code> (mDNS/DNS-SD service discovery — on a server), <code class="" data-line="">bluetooth.service</code> in some configurations, <code class="" data-line="">cups</code> on some RHEL variants, and on Ubuntu, <code class="" data-line="">snapd</code> running and occupying memory along with its associated mount units.</p>
<blockquote><p>
  <strong>Every running service is an attack surface. Every socket it opens is a listening endpoint you didn&#8217;t ask for.</strong>
</p></blockquote>
<h3>SSH configuration out of the box</h3>
<p>The default <code class="" data-line="">sshd_config</code> on most Marketplace images is not hardened. You&#8217;ll typically find:</p>
<pre><code class="" data-line="">PermitRootLogin prohibit-password   # Better than &#039;yes&#039;, but not &#039;no&#039;
PasswordAuthentication no           # Usually disabled by cloud-init — good
X11Forwarding yes                   # On a headless server. Why?
AllowAgentForwarding yes            # Unnecessary for most workloads
PrintLastLog yes                    # Minor, but generates audit noise
MaxAuthTries 6                      # CIS recommends 4 or fewer
ClientAliveInterval 0               # No idle timeout
</code></pre>
<p>CIS Benchmark Level 1 for RHEL 9 has 40+ SSH-specific controls. A default image satisfies perhaps a third of them.</p>
<h3>Kernel parameters that aren&#8217;t tuned</h3>
<pre><code class="" data-line=""># Not set, or not set correctly, on most default images:
net.ipv4.conf.all.send_redirects = 1        # Should be 0
net.ipv4.conf.default.accept_redirects = 1  # Should be 0
net.ipv4.ip_forward = 0                     # Correct if not a router, but often left unset
kernel.randomize_va_space = 2               # Usually correct — verify anyway
fs.suid_dumpable = 0                        # Often not set
kernel.dmesg_restrict = 1                   # Rarely set
</code></pre>
<p>These live in <code class="" data-line="">/etc/sysctl.d/</code> and need to be explicitly applied. In a default AMI, they are not.</p>
<h3>No audit daemon configured</h3>
<p><code class="" data-line="">auditd</code> is installed on most RHEL-family images. It is <strong>not configured</strong>. The default <code class="" data-line="">audit.rules</code> file is essentially empty — the daemon runs but captures almost nothing. On Ubuntu, <code class="" data-line="">auditd</code> isn&#8217;t even installed by default.</p>
<p>CIS Benchmark Level 2 for RHEL 9 specifies 30+ <code class="" data-line="">auditd</code> rules covering file access, privilege escalation, user management changes, network configuration changes, and more. None of them are present in a default AMI.</p>
<h3>Package surface</h3>
<p>Run <code class="" data-line="">rpm -qa | wc -l</code> or <code class="" data-line="">dpkg -l | grep -c ^ii</code> on a fresh instance. AL2023 comes in around 350 packages. Ubuntu 22.04 Server minimal sits around 500. RHEL 9 from Marketplace — depending on the variant — lands between 400 and 600.</p>
<p>How many of those packages does your application actually need? For a Python web service: Python, your runtime dependencies, and a handful of system libraries. The rest is exposure.</p>
<hr />
<p><!-- ── SECTION 3 ───────────────────────────────────────────── --></p>
<h2>The on-prem story is different — and often worse</h2>
<p>Cloud images at least get regular updates from their publishers. On-prem KVM and Nutanix environments tell a different story.</p>
<h3>The KVM / QCOW2 situation</h3>
<p>Most teams running KVM get their base images one of three ways:</p>
<ol>
<li>Download a cloud image (cloud-init enabled QCOW2) from the distro vendor and use it directly</li>
<li>Convert an existing VMware VMDK or OVA and hope for the best</li>
<li>Run a manual Kickstart/Preseed install once, then treat the result as the &#8220;golden image&#8221; forever</li>
</ol>
<p>Option 1 gives you the same problems as the cloud image analysis above, plus you&#8217;re now responsible for handling <code class="" data-line="">cloud-init</code> in an environment that might not have a metadata service — so you either ship a seed ISO with every VM, or you rip out cloud-init and manage first-boot differently.</p>
<p>Option 3 is the most common and the most dangerous. That &#8220;golden image&#8221; was created by someone who&#8217;s possibly no longer at the company, contains packages pinned to versions from 18 months ago, and has <code class="" data-line="">sshd</code> configured however was convenient at the time. Worse, it gets cloned hundreds of times and none of those clones are ever individually updated at the image level.</p>
<h3>The Nutanix AHV specifics</h3>
<p>Nutanix AHV images have additional considerations that cloud images don&#8217;t deal with:</p>
<ul>
<li>AHV uses a custom paravirtualised SCSI controller (<code class="" data-line="">virtio-scsi</code> or the Nutanix variant). Images imported from VMware need <code class="" data-line="">pvscsi</code> drivers removed and <code class="" data-line="">virtio_scsi</code> added to the initramfs before the disk will be detected at boot.</li>
<li>The Nutanix guest tools agent (<code class="" data-line="">ngt</code>) is separate from the kernel and needs to be installed inside the image for snapshot quiescence, VSS integration, and in-guest metrics.</li>
<li><code class="" data-line="">cloud-init</code> works on AHV but requires the <code class="" data-line="">ConfigDrive</code> datasource — not the <code class="" data-line="">EC2</code> datasource that most cloud QCOW2 images default to. An unconfigured datasource means cloud-init times out at boot, costing 3–5 minutes on every first start.</li>
<li>NUMA topology on large AHV nodes affects memory allocation in ways that need kernel tuning (<code class="" data-line="">vm.zone_reclaim_mode</code>, <code class="" data-line="">kernel.numa_balancing</code>) — parameters no generic cloud image sets.</li>
</ul>
<p>The result is that most Nutanix environments end up with a patchwork: partially converted images, manually applied guest tools, and hardening that was done once per environment rather than once per image.</p>
<hr />
<p><!-- ── SECTION 4 ───────────────────────────────────────────── --></p>
<h2>What a hardened image actually looks like</h2>
<p>A properly built hardened image isn&#8217;t just &#8220;a default image with some hardening applied at the end.&#8221; The hardening is architectural — decisions made at <strong>build time</strong> that change the fundamental shape of what&#8217;s inside the image.</p>
<h3>Package set — minimal by design</h3>
<p>Start from a minimal install group — <code class="" data-line="">@minimal-environment</code> on RHEL/Rocky, <code class="" data-line="">--variant=minbase</code> on Debian derivatives. Then add only what the image class requires. For a web server image: your runtime, a process supervisor, and nothing else. No <code class="" data-line="">man-db</code>, no <code class="" data-line="">X11-common</code>, no <code class="" data-line="">avahi</code>.</p>
<blockquote><p>
  <strong>Every package you don&#8217;t install is a CVE that can never affect you.</strong>
</p></blockquote>
<h3>Filesystem hardening</h3>
<p>Separate mount points with restrictive options prevent a class of privilege escalation attacks that depend on executing binaries from world-writable locations:</p>
<pre><code class="" data-line="">/tmp      nodev,nosuid,noexec
/var      nodev,nosuid
/var/tmp  nodev,nosuid,noexec
/home     nodev,nosuid
/dev/shm  nodev,nosuid,noexec
</code></pre>
<p>These are not applied by any default cloud image.</p>
<h3>Kernel parameters — baked in at build time</h3>
<pre><code class="" data-line=""># /etc/sysctl.d/99-hardening.conf

net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv6.conf.all.accept_redirects = 0
kernel.randomize_va_space = 2
fs.suid_dumpable = 0
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
net.core.bpf_jit_harden = 2
</code></pre>
<p>Applied at image build time. Present on every instance, every time, before your application code runs.</p>
<h3>SSH locked down</h3>
<pre><code class="" data-line="">Protocol 2
PermitRootLogin no
MaxAuthTries 4
LoginGraceTime 60
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
PermitUserEnvironment no
Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512
ClientAliveInterval 300
ClientAliveCountMax 3
Banner /etc/issue.net
</code></pre>
<p>This is approximately CIS Level 1 SSH hardening. It lives in the image — not in a post-deploy playbook.</p>
<h3>auditd rules embedded</h3>
<pre><code class="" data-line=""># Privilege escalation
-a always,exit -F arch=b64 -S execve -C uid!=euid -F euid=0 -k setuid

# Sudo usage
-w /etc/sudoers -p wa -k sudoers

# User and group management
-w /etc/passwd -p wa -k identity
-w /etc/group  -p wa -k identity

# Kernel module loading
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules
</code></pre>
<p>The full CIS L2 <code class="" data-line="">auditd</code> ruleset runs to ~60 rules. They&#8217;re all committed to the image. Every instance generates audit logs from minute one of its existence.</p>
<h3>Services disabled at build time</h3>
<pre><code class="" data-line="">systemctl disable avahi-daemon
systemctl disable cups
systemctl disable postfix
systemctl disable bluetooth
systemctl disable rpcbind
systemctl mask debug-shell.service
</code></pre>
<p>The service list varies by distro. The principle is the same: if it&#8217;s not required by the image&#8217;s purpose, it doesn&#8217;t run.</p>
<hr />
<p><!-- ── SECTION 5 ───────────────────────────────────────────── --></p>
<h2>The platform dimension: why you can&#8217;t use one image everywhere</h2>
<p>This is where the complexity gets real. A CIS-hardened RHEL 9 image built for AWS doesn&#8217;t directly work on KVM, and it doesn&#8217;t directly work on Nutanix either. The security controls are the same — the platform-specific layer underneath them is not.</p>
<p>Here&#8217;s what needs to differ per target platform:</p>
<table>
<thead>
<tr>
<th>Concern</th>
<th>AWS (AMI)</th>
<th>KVM (QCOW2)</th>
<th>Nutanix AHV</th>
</tr>
</thead>
<tbody>
<tr>
<td>Disk format</td>
<td>Raw / VMDK → AMI</td>
<td>QCOW2</td>
<td>QCOW2 / VMDK</td>
</tr>
<tr>
<td>Boot mechanism</td>
<td>GRUB2 + PVGRUB2 or UEFI</td>
<td>GRUB2</td>
<td>GRUB2 + UEFI</td>
</tr>
<tr>
<td>Network driver</td>
<td>ENA (ena kernel module)</td>
<td>virtio-net</td>
<td>virtio-net</td>
</tr>
<tr>
<td>Storage driver</td>
<td>NVMe or xen-blkfront</td>
<td>virtio-blk / virtio-scsi</td>
<td>virtio-scsi</td>
</tr>
<tr>
<td>cloud-init datasource</td>
<td>ec2</td>
<td>NoCloud / ConfigDrive</td>
<td>ConfigDrive</td>
</tr>
<tr>
<td>Guest agent</td>
<td>AWS SSM / CloudWatch</td>
<td>qemu-guest-agent</td>
<td>Nutanix Guest Tools</td>
</tr>
<tr>
<td>Metadata service</td>
<td>169.254.169.254</td>
<td>None (seed ISO) or local</td>
<td>Nutanix AOS</td>
</tr>
</tbody>
</table>
<p>A single pipeline needs to produce platform-specific artefacts from a single hardened source. The hardening doesn&#8217;t change. The drivers, datasources, and agents do.</p>
<hr />
<p><!-- ── SECTION 6 ───────────────────────────────────────────── --></p>
<h2>Where this sits relative to CIS and NIST</h2>
<p>The controls described above aren&#8217;t arbitrary. They map directly to published frameworks.</p>
<p><strong>CIS Benchmark Level 1</strong> covers controls with low operational impact and high security return — SSH configuration, kernel parameters, filesystem mount options, service reduction. Almost everything in the &#8220;what a hardened image looks like&#8221; section above is CIS Level 1.</p>
<p><strong>CIS Benchmark Level 2</strong> adds <code class="" data-line="">auditd</code> configuration, PAM controls, additional filesystem protections, and more aggressive service disablement. It trades some operational flexibility for a significantly smaller attack surface.</p>
<p><strong>NIST SP 800-53 CM-6</strong> (Configuration Settings) directly requires that systems be configured to the most restrictive settings consistent with operational requirements. Baking hardening into the image is a stronger implementation of CM-6 than applying it post-deploy — because it&#8217;s guaranteed, auditable at build time, and consistent across every instance regardless of how it was launched.</p>
<p><strong>NIST SP 800-53 SI-2</strong> (Flaw Remediation) maps to your image patching cadence. An image rebuilt monthly against the latest package repositories satisfies SI-2 more completely than runtime patching alone, because it also eliminates packages you don&#8217;t need — packages that would need patching if they were present.</p>
<blockquote><p>
  The full CIS and NIST control mapping will be covered in depth later in this series.
</p></blockquote>
<hr />
<p><!-- ── SECTION 7 ───────────────────────────────────────────── --></p>
<h2>The build-time vs runtime hardening distinction</h2>
<p>This is the most important concept in the entire post.</p>
<p>Hardening applied at <strong>runtime</strong> — via Ansible, Chef, cloud-init user-data, or a shell script — is conditional. It runs <em>if</em> the automation runs. It applies <em>if</em> nothing fails. It&#8217;s consistent only if every deployment goes through exactly the same path.</p>
<p>Hardening embedded in the <strong>image</strong> is unconditional. It cannot be skipped. It doesn&#8217;t depend on connectivity to an Ansible control node. It doesn&#8217;t require cloud-init to succeed. It cannot be accidentally omitted by a new team member who doesn&#8217;t know the runbook.</p>
<p>This distinction matters most at incident response time. When you&#8217;re investigating a compromised instance, the first question you want to answer confidently is: <em>was this instance ever in a known-good state?</em></p>
<ul>
<li>If your hardening is in the <strong>image</strong>: yes, from boot.</li>
<li>If your hardening is applied <strong>post-deploy</strong>: it depends on whether everything went right on that specific instance&#8217;s first boot.</li>
</ul>
<hr />
<p><!-- ── SECTION 8 — NEXT STEPS ─────────────────────────────── --></p>
<h2>What comes next</h2>
<p>The practical question this raises: how do you build these images in a repeatable, multi-platform way, with CIS scanning integrated into the build pipeline?</p>
<p>Packer covers most of the builder layer. OpenSCAP provides the scanning. Kickstart, cloud-init, and Nutanix AHV-specific tooling fill the gaps. But the orchestration between these — producing a consistent hardened image for three different target platforms from a single source of truth — is where most teams hit friction.</p>
<p>The next post in this series covers the platform-specific differences between AWS, KVM, and Nutanix in depth: what actually needs to change per target when your security baseline is shared.</p>
<p><strong>Next in the series:</strong> <a href="#">Cloud vs KVM vs Nutanix — why one image doesn&#8217;t fit all →</a></p>
<hr />
<p><em>Questions or corrections? Open an issue or reach me on <a href="https://www.linkedin.com/in/vamshikrishnasanthapuri/" target="_blank" rel="noopener">LinkedIn</a>. If this was useful, the series index has the full roadmap.</em></p>
<p><a class="a2a_button_mastodon" href="https://www.addtoany.com/add_to/mastodon?linkurl=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&amp;linkname=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" title="Mastodon" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&amp;linkname=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&amp;linkname=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&amp;linkname=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" title="Reddit" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_x" href="https://www.addtoany.com/add_to/x?linkurl=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&amp;linkname=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" title="X" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&amp;linkname=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_copy_link" href="https://www.addtoany.com/add_to/copy_link?linkurl=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&amp;linkname=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" title="Copy Link" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Flinuxcent.com%2Fcloud-ami-security-risks-custom-os-images%2F&#038;title=Cloud%20AMI%20Security%20Risks%20%26%20How%20Custom%20OS%20Images%20Fix%20them%20and%20what%E2%80%99s%20wrong%20with%20defaults" data-a2a-url="https://linuxcent.com/cloud-ami-security-risks-custom-os-images/" data-a2a-title="Cloud AMI Security Risks &amp; How Custom OS Images Fix them and what’s wrong with defaults"></a></p><p>The post <a href="https://linuxcent.com/cloud-ami-security-risks-custom-os-images/">Cloud AMI Security Risks &#038; How Custom OS Images Fix them and what&#8217;s wrong with defaults</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://linuxcent.com/cloud-ami-security-risks-custom-os-images/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1421</post-id>	</item>
		<item>
		<title>EKS 1.33 Upgrade Blocker: Fixing Dead Nodes &#038; NetworkManager on Rocky Linux</title>
		<link>https://linuxcent.com/eks-1-33-networkmanager-systemd-networkd-migration-fix/</link>
					<comments>https://linuxcent.com/eks-1-33-networkmanager-systemd-networkd-migration-fix/#respond</comments>
		
		<dc:creator><![CDATA[Vamshi Krishna Santhapuri]]></dc:creator>
		<pubDate>Tue, 17 Feb 2026 19:42:18 +0000</pubDate>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Devops]]></category>
		<category><![CDATA[Linux Tutorials]]></category>
		<category><![CDATA[SRE]]></category>
		<category><![CDATA[Troubleshooting]]></category>
		<category><![CDATA[AMI Build]]></category>
		<category><![CDATA[AWS EKS]]></category>
		<category><![CDATA[AWS networking]]></category>
		<category><![CDATA[cloud-init]]></category>
		<category><![CDATA[CoreDNS]]></category>
		<category><![CDATA[Kubernetes 1.33]]></category>
		<category><![CDATA[NetworkManager]]></category>
		<category><![CDATA[Packer]]></category>
		<category><![CDATA[resolv.conf]]></category>
		<category><![CDATA[Rocky Linux EKS]]></category>
		<category><![CDATA[systemd-networkd]]></category>
		<category><![CDATA[systemd-networkd migration]]></category>
		<category><![CDATA[systemd-resolved]]></category>
		<category><![CDATA[VPC]]></category>
		<guid isPermaLink="false">https://linuxcent.com/?p=1400</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 5</span> <span class="rt-label rt-postfix">minutes</span></span>The EKS 1.33+ NetworkManager Trap: A Complete systemd-networkd Migration Guide for Rocky &#038; Alma Linux TL;DR: The Blocker: Upgrading to EKS 1.33+ is breaking worker nodes, especially on free community distributions like Rocky Linux and AlmaLinux. Boot times are spiking past 6 minutes, and nodes are failing to get IPs. The Root Cause: AWS is ... <a title="EKS 1.33 Upgrade Blocker: Fixing Dead Nodes &#038; NetworkManager on Rocky Linux" class="read-more" href="https://linuxcent.com/eks-1-33-networkmanager-systemd-networkd-migration-fix/" aria-label="Read more about EKS 1.33 Upgrade Blocker: Fixing Dead Nodes &#038; NetworkManager on Rocky Linux">Read more</a></p>
<p>The post <a href="https://linuxcent.com/eks-1-33-networkmanager-systemd-networkd-migration-fix/">EKS 1.33 Upgrade Blocker: Fixing Dead Nodes &#038; NetworkManager on Rocky Linux</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 5</span> <span class="rt-label rt-postfix">minutes</span></span><h1>The EKS 1.33+ NetworkManager Trap: A Complete systemd-networkd Migration Guide for Rocky &#038; Alma Linux</h1>
<h2>TL;DR:</h2>
<ul>
<li><strong>The Blocker:</strong> Upgrading to EKS 1.33+ is breaking worker nodes, especially on free community distributions like Rocky Linux and AlmaLinux. Boot times are spiking past 6 minutes, and nodes are failing to get IPs.</li>
<li><strong>The Root Cause:</strong> AWS is deprecating <code class="" data-line="">NetworkManager</code> in favor of <code class="" data-line="">systemd-networkd</code>. However, ripping out NetworkManager can leave stale VPC IPs in <code class="" data-line="">/etc/resolv.conf</code>. Combined with the <code class="" data-line="">systemd-resolved</code> stub listener (<code class="" data-line="">127.0.0.53</code>) and a few configuration missteps, it causes a total internal DNS collapse where CoreDNS pods crash and burn.</li>
<li><strong>The Subtext:</strong> AWS is pushing this modern networking standard hard. Subtly, this acts as a major drawback for Rocky/Alma AMIs, silently steering frustrated engineers toward Amazon Linux 2023 (AL2023) as the &#8220;easy&#8221; way out.</li>
<li><strong>The &#8220;Super Hack&#8221;:</strong> Automate the clean removal of NetworkManager, bypass the DNS stub listener by symlinking <code class="" data-line="">/etc/resolv.conf</code> directly to the <code class="" data-line="">systemd</code> uplink, and enforce strict state validation during the AMI build.</li>
</ul>
<hr>
<p>If you’ve been in the DevOps and SRE space long enough, you know that vendor upgrades rarely go exactly as planned. But lately, if you are running enterprise Linux distributions like Rocky Linux or AlmaLinux on AWS EKS, you might have noticed the ground silently shifting beneath your feet.</p>
<p>With the push to EKS 1.33+, AWS is mandating a shift toward modern, cloud-native networking standards. Specifically, they are phasing out the legacy <code class="" data-line="">NetworkManager</code> in favor of <code class="" data-line="">systemd-networkd</code>.</p>
<p>While this makes sense on paper, the transition for community distributions has been incredibly painful. AWS support couldn&#8217;t resolve our issues, and my SRE team had practically given up, officially halting our EKS upgrade process. It’s hard not to notice that this massive, undocumented friction in Rocky Linux and AlmaLinux conveniently positions AWS&#8217;s own Amazon Linux 2023 (AL2023) as the path of least resistance.</p>
<p>I’m hoping the incredible maintainers at free distributions like Rocky Linux and AlmaLinux take note of this architectural shift. But until the official AMIs catch up, we have to fix it ourselves. Here is the exact breakdown of the cascading failure that brought our clusters to their knees, and the &#8220;super hack&#8221; script we used to fix it.</p>
<h2>The Investigation: A Cascading SRE Failure</h2>
<p>When our EKS 1.33+ worker nodes started booting with 6+ minute latencies or outright failing to join the cluster, I pulled apart our Rocky Linux AMIs to monitor the network startup sequence. What I found was a classic cascading failure of services, stale data, and human error.</p>
<h3>Step 1: The Race Condition</h3>
<p>Initially, the problem was a violent tug-of-war. <code class="" data-line="">NetworkManager</code> was not correctly disabled by default, and <code class="" data-line="">cloud-init</code> was still trying to invoke it. This conflicted directly with <code class="" data-line="">systemd-networkd</code>, paralyzing the network stack during boot. To fix this, we initially disabled the <code class="" data-line="">NetworkManager</code> service and removed it from <code class="" data-line="">cloud-init</code>.</p>
<h3>Step 2: The Stale Data Landmine</h3>
<p>Here is where the trap snapped shut. Because <code class="" data-line="">NetworkManager</code> was historically the primary service responsible for dynamically generating and updating <code class="" data-line="">/etc/resolv.conf</code>, completely disabling it stopped that file from being updated.</p>
<p>When we baked the new AMI via Packer, <code class="" data-line="">/etc/resolv.conf</code> was orphaned and preserved the old configuration—specifically, a stale <code class="" data-line="">.2</code> VPC IP address from the temporary subnet where the AMI build ran.</p>
<h3>Step 3: The Human Element</h3>
<p>We&#8217;ve all been there: during a stressful outage, wires get crossed. While troubleshooting the dead nodes, one of our SREs mistakenly stopped the <code class="" data-line="">systemd-resolved</code> service entirely, thinking it was conflicting with something else.</p>
<h3>Step 4: Total DNS Collapse</h3>
<p>When the new AMI booted up and joined the EKS node group, the environment was a disaster zone:</p>
<ol>
<li><code class="" data-line="">NetworkManager</code> was dead (intentional).</li>
<li><code class="" data-line="">systemd-resolved</code> was stopped (accidental).</li>
<li><code class="" data-line="">/etc/resolv.conf</code> contained a dead, stale IP address from a completely different subnet.</li>
</ol>
<p>When <code class="" data-line="">kubelet</code> started, it dutifully read the host&#8217;s broken <code class="" data-line="">/etc/resolv.conf</code> and passed it up to CoreDNS. CoreDNS attempted to route traffic to the stale IP, failed, and started crash-looping. Internal DNS resolution (<code class="" data-line="">pod.namespace.svc.cluster.local</code>) totally collapsed. The cluster was dead in the water.</p>
<figure class="wp-block-image size-large">
<img fetchpriority="high" decoding="async" src="[https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-EKS-Cascading-Failure.jpg](https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-EKS-Cascading-Failure.jpg)" alt="Flowchart showing the cascading DNS failure in EKS worker nodes" width="221" height="661" class="alignnone size-full wp-image-1410" srcset="https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-EKS-Cascading-Failure.jpg 221w, https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-EKS-Cascading-Failure-100x300.jpg 100w" sizes="(max-width: 221px) 100vw, 221px" /><figcaption>The perfect storm: How stale data and disabled services led to a total CoreDNS collapse.</figcaption><hr>
<h2>Linux Internals: How systemd Manages DNS (And Why CoreDNS Breaks)</h2>
<p>To understand how to permanently fix this, we need to look at how <code class="" data-line="">systemd</code> actually handles DNS under the hood. When using <code class="" data-line="">systemd-networkd</code>, <code class="" data-line="">resolv.conf</code> management is handled through a strict partnership with <code class="" data-line="">systemd-resolved</code>. </p>
<figure class="wp-block-image size-large">
<img decoding="async" src="[https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-Page-2-1024x299.jpg](https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-Page-2-1024x299.jpg)" alt="Architecture diagram of systemd-networkd and systemd-resolved D-Bus communication" width="1024" height="299" class="alignnone size-large wp-image-1411" srcset="https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-Page-2-1024x299.jpg 1024w, https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-Page-2-300x87.jpg 300w, https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-Page-2-768x224.jpg 768w, https://linuxcent.com/wp-content/uploads/2026/02/Untitled-Diagram-Page-2.jpg 1101w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>How systemd collects network data and the critical symlink choice that dictates EKS DNS health.</figcaption><p>Here is how the flow works: <code class="" data-line="">systemd-networkd</code> collects network and DNS information (from DHCP, Router Advertisements, or static configs) and pushes it to <code class="" data-line="">systemd-resolved</code> via D-Bus. To manage your DNS resolution effectively, you must configure the <code class="" data-line="">/etc/resolv.conf</code> symbolic link to match your desired mode of operation. You have three choices:</p>
<h3>1. The &#8220;Recommended&#8221; Local DNS Stub (The EKS Killer)</h3>
<p>By default, systemd recommends using <code class="" data-line="">systemd-resolved</code> as a local DNS cache and manager, providing features like DNS-over-TLS and mDNS.</p>
<ul>
<li><strong>The Symlink:</strong> <code class="" data-line="">ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf</code></li>
<li><strong>Contents:</strong> Points to <code class="" data-line="">127.0.0.53</code> as the only nameserver.</li>
<li><strong>The Problem:</strong> This is a disaster for Kubernetes. If Kubelet passes <code class="" data-line="">127.0.0.53</code> to CoreDNS, CoreDNS queries its own loopback interface inside the pod network namespace, blackholing all cluster DNS.</li>
</ul>
<h3>2. Direct Uplink DNS (The &#8220;Super Hack&#8221; Solution)</h3>
<p>This mode bypasses the local stub entirely. The system lists the actual upstream DNS servers (e.g., your AWS VPC nameservers) discovered by <code class="" data-line="">systemd-networkd</code> directly in the file.</p>
<ul>
<li><strong>The Symlink:</strong> <code class="" data-line="">ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf</code></li>
<li><strong>Contents:</strong> Lists all actual VPC DNS servers currently known to <code class="" data-line="">systemd-resolved</code>.</li>
<li><strong>The Benefit:</strong> CoreDNS gets the real AWS VPC nameservers, allowing it to route external queries correctly while managing internal cluster resolution perfectly.</li>
</ul>
<h3>3. Static Configuration (Manual)</h3>
<p>If you want to manage DNS manually without systemd modifying the file, you break the symlink and create a regular file (<code class="" data-line="">rm /etc/resolv.conf</code>). While <code class="" data-line="">systemd-networkd</code> still receives DNS info from DHCP, it won&#8217;t touch this file. (Not ideal for dynamic cloud environments).</p>
<hr>
<h2>The Solution: A Surgical systemd Cutover</h2>
<p>Knowing the internals, the path forward is clear. We needed to not only remove the legacy stack but explicitly rewire the DNS resolution to the <strong>Direct Uplink</strong> to prevent the stale data trap and bypass the notorious <code class="" data-line="">127.0.0.53</code> stub listener.</p>
<p>Here is the exact state we achieved:</p>
<ol>
<li><strong>Lock down <code class="" data-line="">cloud-init</code></strong> so it stops triggering legacy network services.</li>
<li><strong>Completely mask <code class="" data-line="">NetworkManager</code></strong> to ensure it never wakes up.</li>
<li><strong>Ensure <code class="" data-line="">systemd-resolved</code> is enabled and running</strong>, but with the <code class="" data-line="">DNSStubListener</code> explicitly disabled (<code class="" data-line="">DNSStubListener=no</code>) so it doesn&#8217;t conflict with anything.</li>
<li><strong>Destroy the stale <code class="" data-line="">/etc/resolv.conf</code></strong> and create a symlink to the <strong>Direct Uplink</strong> (<code class="" data-line="">ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf</code>).</li>
<li><strong>Reconfigure and restart <code class="" data-line="">systemd-networkd</code></strong>.</li>
</ol>
<blockquote><p>
<strong>Pro-Tip for Debugging:</strong> To ensure <code class="" data-line="">systemd-networkd</code> is successfully pushing DNS info to the resolver, verify your <code class="" data-line="">.network</code> files in <code class="" data-line="">/etc/systemd/network/</code>. Ensure <code class="" data-line="">UseDNS=yes</code> (which is the default) is set in the <code class="" data-line="">[DHCPv4]</code> section. You can always run <code class="" data-line="">resolvectl status</code> to see exactly which DNS servers are currently assigned to each interface over D-Bus!
</p></blockquote>
<h2>The Automation: Production AMI Prep Script</h2>
<p>Manual hacks are great for debugging, but SRE is about repeatable automation. We&#8217;ve open-sourced the <code class="" data-line="">eks-production-ami-prep.sh</code> script to handle this cutover automatically during your Packer or Image Builder pipeline. It standardizes the cutover, wipes out the stale data, and includes a strict validation suite.</p>
<div class="wp-block-buttons">
<div class="wp-block-button"><a class="wp-block-button__link" href="//github.com/rrskris/NetworkManager-systemd-networkd-config/blob/main/eks-production-ami-prep.sh" target="_blank" rel="noreferrer noopener">View Migration Script on GitHub</a></div>
</div>
<p></br></p>
<h2>The Results</h2>
<p>By actively taking control of the <code class="" data-line="">systemd</code> stack and ensuring <code class="" data-line="">/etc/resolv.conf</code> was dynamically linked rather than statically abandoned, we completely unblocked our EKS 1.33+ upgrade.</p>
<p>More impressively, <strong>our system bootup time dropped from a crippling 6+ minutes down to under 2 minutes.</strong> We shouldn&#8217;t have to abandon fantastic, free enterprise distributions just because a cloud provider shifts their networking paradigm. If your team is struggling with AWS EKS upgrades on Rocky Linux or AlmaLinux, integrate this automation into your pipeline and get your clusters back in the fast lane.</p>
<p><a class="a2a_button_mastodon" href="https://www.addtoany.com/add_to/mastodon?linkurl=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&amp;linkname=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" title="Mastodon" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&amp;linkname=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&amp;linkname=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&amp;linkname=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" title="Reddit" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_x" href="https://www.addtoany.com/add_to/x?linkurl=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&amp;linkname=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" title="X" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&amp;linkname=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_copy_link" href="https://www.addtoany.com/add_to/copy_link?linkurl=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&amp;linkname=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" title="Copy Link" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Flinuxcent.com%2Feks-1-33-networkmanager-systemd-networkd-migration-fix%2F&#038;title=EKS%201.33%20Upgrade%20Blocker%3A%20Fixing%20Dead%20Nodes%20%26%20NetworkManager%20on%20Rocky%20Linux" data-a2a-url="https://linuxcent.com/eks-1-33-networkmanager-systemd-networkd-migration-fix/" data-a2a-title="EKS 1.33 Upgrade Blocker: Fixing Dead Nodes &amp; NetworkManager on Rocky Linux"></a></p><p>The post <a href="https://linuxcent.com/eks-1-33-networkmanager-systemd-networkd-migration-fix/">EKS 1.33 Upgrade Blocker: Fixing Dead Nodes &#038; NetworkManager on Rocky Linux</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://linuxcent.com/eks-1-33-networkmanager-systemd-networkd-migration-fix/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1400</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: linuxcent.com @ 2026-08-22 11:33:41 by W3 Total Cache
-->