<?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>Multi-Cloud Archives - Linuxcent</title>
	<atom:link href="https://linuxcent.com/tag/multi-cloud/feed/" rel="self" type="application/rss+xml" />
	<link>https://linuxcent.com/tag/multi-cloud/</link>
	<description>Infrastructure security, from the kernel up.</description>
	<lastBuildDate>Mon, 27 Jul 2026 11:57:05 +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>Multi-Cloud Archives - Linuxcent</title>
	<link>https://linuxcent.com/tag/multi-cloud/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">211632295</site>	<item>
		<title>One Blueprint, Six Clouds — Multi-Provider OS Image Builds</title>
		<link>https://linuxcent.com/linux-hardening-multi-cloud/</link>
					<comments>https://linuxcent.com/linux-hardening-multi-cloud/#respond</comments>
		
		<dc:creator><![CDATA[Vamshi Krishna Santhapuri]]></dc:creator>
		<pubDate>Sun, 26 Apr 2026 19:41:36 +0000</pubDate>
				<category><![CDATA[OS Image Builder]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[BakeX]]></category>
		<category><![CDATA[DevSecOps]]></category>
		<category><![CDATA[GCP]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Multi-Cloud]]></category>
		<category><![CDATA[OS Hardening]]></category>
		<guid isPermaLink="false">https://linuxcent.com/linux-hardening-multi-cloud/</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"> 7</span> <span class="rt-label rt-postfix">minutes</span></span>One HardeningBlueprint YAML, six cloud providers: AWS, GCP, Azure, DigitalOcean, Linode, Proxmox. How Stratum handles provider differences so your compliance intent stays portable.</p>
<p>The post <a href="https://linuxcent.com/linux-hardening-multi-cloud/">One Blueprint, Six Clouds — Multi-Provider OS Image Builds</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"> 7</span> <span class="rt-label rt-postfix">minutes</span></span><style>
pre{position:relative;background:#1e1e1e;color:#d4d4d4;
    padding:16px 16px 16px 20px;border-radius:6px;overflow-x:auto;
    font-family:'JetBrains Mono','Fira Code','Cascadia Code',Consolas,'Courier New',monospace;
    font-size:.88em;line-height:1.6;border-left:4px solid #555}
code{background:#f4f4f4;padding:2px 5px;border-radius:3px;font-size:.9em}
pre code{background:transparent;padding:0;color:inherit}
pre[data-lang="bash"],pre[data-lang="sh"],
pre[data-lang="shell"],pre[data-lang="zsh"]{border-left-color:#4ec9b0}
pre[data-lang="yaml"],pre[data-lang="json"],
pre[data-lang="toml"],pre[data-lang="xml"]{border-left-color:#569cd6}
pre[data-lang="python"],pre[data-lang="go"],pre[data-lang="rust"],
pre[data-lang="java"],pre[data-lang="c"],pre[data-lang="cpp"]{border-left-color:#c586c0}
pre[data-lang="text"],pre[data-lang="output"],
pre[data-lang="console"]{border-left-color:#888}
.lc-copy-btn{position:absolute;top:8px;right:8px;background:#2d2d2d;color:#ccc;
    border:1px solid #444;border-radius:4px;padding:3px 9px;font-size:.75em;
    font-family:system-ui,sans-serif;cursor:pointer;opacity:0;
    transition:opacity .15s,background .15s;line-height:1.6}
pre:hover .lc-copy-btn{opacity:1}
.lc-copy-btn:hover{background:#3a3a3a;color:#fff}
.lc-copy-btn.copied{color:#4ec9b0;border-color:#4ec9b0}
.lc-lang-badge{position:absolute;top:8px;left:20px;font-family:system-ui,sans-serif;
    font-size:.7em;color:#666;text-transform:uppercase;letter-spacing:.04em;
    line-height:1;pointer-events:none;opacity:0;transition:opacity .15s}
pre:hover .lc-lang-badge{opacity:1}
table{border-collapse:collapse;width:100%;margin:16px 0}
th,td{border:1px solid #ddd;padding:10px 14px;text-align:left}
th{background:#f0f0f0;font-weight:600}
tr:nth-child(even){background:#fafafa}
</style>
<p><script>
(function(){
  if(window.__lcCodeEnhanced)return;
  window.__lcCodeEnhanced=true;
  function enhance(){
    document.querySelectorAll('pre').forEach(function(pre){
      var code=pre.querySelector('code');
      var lang='';
      if(code){var m=(code.className||'').match(/language-(\S+)/);if(m)lang=m[1].toLowerCase();}
      if(lang)pre.setAttribute('data-lang',lang);
      if(lang){var badge=document.createElement('span');badge.className='lc-lang-badge';badge.textContent=lang;pre.insertBefore(badge,pre.firstChild);}
      var btn=document.createElement('button');
      btn.className='lc-copy-btn';btn.textContent='Copy';btn.setAttribute('aria-label','Copy code to clipboard');
      pre.appendChild(btn);
      btn.addEventListener('click',function(){
        var text=code?code.innerText:pre.innerText;
        if(navigator.clipboard&&window.isSecureContext){
          navigator.clipboard.writeText(text).then(function(){ok(btn);}).catch(function(){fb(text,btn);});
        }else{fb(text,btn);}
      });
    });
  }
  function ok(btn){btn.textContent='Copied!';btn.classList.add('copied');setTimeout(function(){btn.textContent='Copy';btn.classList.remove('copied');},2000);}
  function fb(text,btn){
    try{var ta=document.createElement('textarea');ta.value=text;ta.style.cssText='position:fixed;left:-9999px;top:-9999px;opacity:0';document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);ok(btn);}
    catch(e){btn.textContent='✗ Failed';setTimeout(function(){btn.textContent='Copy';},2000);}
  }
  if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',enhance);}else{enhance();}
})();
</script></p>
<p><em>OS Hardening as Code, Episode 3</em><br />
<em><a href="https://linuxcent.com/cloud-ami-security-risks-custom-os-images/">Cloud AMI Security Risks</a> · <a href="https://linuxcent.com/linux-hardening-as-code/">Linux Hardening as Code</a> · </em><em>Multi-Cloud OS Hardening</em>**</p>
<blockquote>
<p><strong>Note:</strong> the tool in this series was released as <strong>Stratum</strong> and renamed to <strong>BakeX</strong> at<br />
v0.6.0 — same project, same license, same team. Commands below use the current <code class="" data-line="">bakex</code><br />
CLI. If you arrived here looking for <code class="" data-line="">stratum</code> or <code class="" data-line="">pip install stratumoss</code>, you&#8217;re in the<br />
right place: <a href="https://github.com/invicton/bakex">github.com/invicton/bakex</a>.</p>
</blockquote>
<hr />
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Multi-cloud OS hardening with separate scripts per provider means three scripts that drift within weeks</li>
<li>A HardeningBlueprint YAML separates compliance intent (portable) from provider details (handled by BakeX&#8217;s provider layer)</li>
<li>You keep one blueprint file per provider — and every section except <code class="" data-line="">target</code> stays byte-identical across all six. The diff below proves it</li>
<li>Provider-specific differences — disk names, cloud-init ordering, base image identifiers — are abstracted away from the blueprint author</li>
<li>The compliance posture becomes reviewable in a pull request: a control change touches six files identically, and a reviewer can see that at a glance</li>
<li>Six providers ship as working blueprints today: AWS, GCP, Azure, DigitalOcean, Linode, Proxmox</li>
</ul>
<hr />
<h2 id="the-problem-three-clouds-three-scripts-three-ways-to-drift">The Problem: Three Clouds, Three Scripts, Three Ways to Drift</h2>
<pre><code class="" data-line="">AWS hardening script          GCP hardening script          Azure hardening script
├── /dev/xvd* disk refs       ├── /dev/sda* disk refs       ├── /dev/sda* disk refs
├── 169.254.169.254 IMDS      ├── 169.254.169.254 IMDS      ├── 169.254.169.254 IMDS
├── cloud-init order A        ├── cloud-init order B        ├── cloud-init order C
└── Updated: Jan 2025         └── Updated: Aug 2024         └── Updated: Mar 2024
                                         │
                                         └─ 5 months behind
                                            on CIS updates
</code></pre>
<p>Multi-cloud OS hardening starts as a copy-paste of the AWS script. Within a month, the clouds diverge.</p>
<p>EP02 showed that a HardeningBlueprint YAML eliminates the skip-at-2am problem by making hardening a build artifact. What it assumed — quietly — is that you&#8217;re building for one provider. The moment you expand to a second cloud, the provider-specific details in the blueprint become a problem: disk names differ, cloud-init fires in a different order, and AWS-specific assumptions break silently on GCP.</p>
<hr />
<p>We expanded from AWS to GCP six months ago. The EC2 hardening script had been working reliably for over a year. The GCP engineer took the AWS script, made some quick changes, and started building images.</p>
<p>The first GCP images had a subtle problem: the <code class="" data-line="">/tmp</code> and <code class="" data-line="">/home</code> separate partition entries in <code class="" data-line="">/etc/fstab</code> referenced <code class="" data-line="">/dev/xvdb</code> — an AWS disk naming convention. GCP uses <code class="" data-line="">/dev/sdb</code>. The fstab entries were silently ignored. The mounts existed but weren&#8217;t restricted. The CIS controls for separate filesystem partitions were listed as passing in the scan output because the Ansible task had &#8220;run successfully&#8221; — it just hadn&#8217;t done what we thought.</p>
<p>It took a pentest three months later to catch it. The finding: six production GCP instances with <code class="" data-line="">/tmp</code> not mounted with <code class="" data-line="">noexec, nosuid, nodev</code> — despite our &#8220;CIS L1 hardened&#8221; label.</p>
<p>The root cause wasn&#8217;t the engineer. It was a hardening approach that required cloud-specific knowledge embedded in the script rather than in a provider abstraction layer.</p>
<hr />
<h2 id="how-bakex-separates-compliance-intent-from-provider-details">How BakeX Separates Compliance Intent from Provider Details</h2>
<p>Multi-cloud OS hardening works when the compliance intent and the provider details are kept strictly separate.</p>
<pre><code class="" data-line="">HardeningBlueprint YAML
(compliance intent — portable)
         │
         ▼
  BakeX Provider Layer
  ┌─────────────────────────────────────────────┐
  │  AWS         │  GCP         │  Azure        │
  │  /dev/xvd*   │  /dev/sda*   │  /dev/sda*    │
  │  IMDS v2     │  GCP IMDS    │  Azure IMDS   │
  │  cloud-init  │  cloud-init  │  waagent       │
  │  order A     │  order B     │  order C       │
  └─────────────────────────────────────────────┘
         │
         ▼
  Ansible-Lockdown + Provider-Aware Configuration
         │
         ▼
  OpenSCAP Scan
         │
         ▼
  Golden Image (AMI / GCP Image / Azure Image)
</code></pre>
<p>The blueprint author declares <strong>what</strong> should be true about the OS. BakeX&#8217;s provider layer handles <strong>how</strong> that&#8217;s achieved on each cloud.</p>
<p>The disk naming, cloud-init sequencing, metadata endpoint configuration, and provider-specific package repositories are all abstracted into the provider layer. They never appear in the blueprint file.</p>
<hr />
<h2 id="the-same-blueprint-across-six-providers">The Same Blueprint Across Six Providers</h2>
<p>Here is the part people expect to be a flag, and isn&#8217;t. There is no <code class="" data-line="">--provider</code> switch. The<br />
provider is a field <em>inside</em> the blueprint, so you keep one file per target:</p>
<pre><code class="" data-line="">$ ls blueprints/ubuntu/22.04/
cis-l1-aws.yaml           cis-l1-digitalocean.yaml  cis-l1-linode.yaml
cis-l1-azure.yaml         cis-l1-gcp.yaml           cis-l1-proxmox.yaml

# Validate all six at once — offline, no cloud API calls
$ bakex validate blueprints/ubuntu/22.04/*.yaml
OK    blueprints/ubuntu/22.04/cis-l1-aws.yaml  (HardeningBlueprint &#039;ubuntu22-cis-l1-aws&#039;)
...
6/6 blueprint(s) valid.

# Build one
$ bakex build blueprints/ubuntu/22.04/cis-l1-gcp.yaml
Building &#039;ubuntu22-cis-l1-gcp&#039; (gcp) → job 7f3c9e82-…
</code></pre>
<p>That design choice looks like more files, and it is. What you get for it is that a blueprint<br />
is completely self-describing: the file names its own cloud and its own base image, so it<br />
builds the same way on your laptop, in CI, and on a colleague&#8217;s machine with no flags to<br />
forget and no environment to match.</p>
<p><strong>The claim worth testing: how much actually differs between those six files?</strong></p>
<p>I parsed all six and compared every section except <code class="" data-line="">metadata</code> and <code class="" data-line="">target</code>:</p>
<pre><code class="" data-line="">compliance    identical across all 6
controls      identical across all 6   (same rules, same enable state)
filesystem    identical across all 6
users         identical across all 6
system        identical across all 6
</code></pre>
<p>Only the <code class="" data-line="">target</code> block changes, and it changes in exactly the way you&#8217;d expect:</p>
<table>
<thead>
<tr>
<th>Provider</th>
<th><code class="" data-line="">instance_type</code></th>
<th><code class="" data-line="">base_image</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>aws</td>
<td><code class="" data-line="">t3.medium</code></td>
<td><code class="" data-line="">ami-0c7217cdde317cfec</code></td>
</tr>
<tr>
<td>gcp</td>
<td><code class="" data-line="">e2-medium</code></td>
<td><code class="" data-line="">projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts</code></td>
</tr>
<tr>
<td>azure</td>
<td><code class="" data-line="">Standard_B2s</code></td>
<td><code class="" data-line="">Canonical:0001-com-ubuntu-server-jammy:22_04-lts-gen2:latest</code></td>
</tr>
<tr>
<td>digitalocean</td>
<td><code class="" data-line="">s-2vcpu-4gb</code></td>
<td><code class="" data-line="">ubuntu-22-04-x64</code></td>
</tr>
<tr>
<td>linode</td>
<td><code class="" data-line="">g6-standard-2</code></td>
<td><code class="" data-line="">linode/ubuntu22.04</code></td>
</tr>
<tr>
<td>proxmox</td>
<td><code class="" data-line="">2c-4g</code></td>
<td><code class="" data-line="">9000</code> (VE template VMID)</td>
</tr>
</tbody>
</table>
<p>Six wildly different ways of naming &#8220;Ubuntu 22.04 LTS&#8221; and sizing a 2 vCPU / 4 GB box. That<br />
is the entire provider-specific surface. The CIS benchmark, the profile, the datastream, the<br />
mount options, the locked root account, the control overrides and their justifications — all<br />
byte-identical.</p>
<p>One honest caveat, because I checked rather than assumed: the six files are <em>semantically</em><br />
identical but not textually so. The justification string on one disabled SELinux rule is<br />
worded slightly differently between files — same rule, same <code class="" data-line="">enabled: false</code>, same meaning,<br />
different prose. It&#8217;s a cosmetic inconsistency in the shipped library, not a behavioural one,<br />
and it&#8217;s the kind of thing you only find by diffing rather than trusting the header comment.</p>
<p>If you change the compliance posture — add a control override, tighten a mount option — you<br />
change it identically in six files and rebuild. A reviewer sees six identical hunks in the<br />
diff. A sixth hunk that looks different is a bug, and it&#8217;s visible in code review rather than<br />
three months later in a pentest.</p>
<hr />
<h2 id="what-the-provider-layer-handles">What the Provider Layer Handles</h2>
<p>The provider layer is where the cloud-specific knowledge lives, so the blueprint author doesn&#8217;t have to carry it:</p>
<p><strong>Disk naming:</strong></p>
<table>
<thead>
<tr>
<th>Provider</th>
<th>OS disk</th>
<th>Ephemeral</th>
<th>Data</th>
</tr>
</thead>
<tbody>
<tr>
<td>AWS</td>
<td><code class="" data-line="">/dev/xvda</code></td>
<td><code class="" data-line="">/dev/xvdb</code></td>
<td><code class="" data-line="">/dev/xvdc+</code></td>
</tr>
<tr>
<td>GCP</td>
<td><code class="" data-line="">/dev/sda</code></td>
<td>—</td>
<td><code class="" data-line="">/dev/sdb+</code></td>
</tr>
<tr>
<td>Azure</td>
<td><code class="" data-line="">/dev/sda</code></td>
<td><code class="" data-line="">/dev/sdb</code> (temp disk)</td>
<td><code class="" data-line="">/dev/sdc+</code></td>
</tr>
<tr>
<td>DigitalOcean</td>
<td><code class="" data-line="">/dev/vda</code></td>
<td>—</td>
<td><code class="" data-line="">/dev/vdb+</code></td>
</tr>
</tbody>
</table>
<p>The CIS controls for separate <code class="" data-line="">/tmp</code> and <code class="" data-line="">/home</code> partitions reference disk paths that differ across these providers. The provider layer translates the blueprint&#8217;s <code class="" data-line="">filesystem.tmp</code> declaration into the correct fstab entries for the target cloud.</p>
<p><strong>Cloud-init ordering:</strong></p>
<p>Different providers initialize services in different orders. On AWS, the network is available before cloud-init runs most tasks. On GCP, some network configuration happens after cloud-init starts. On Azure, the waagent handles some configuration that cloud-init handles elsewhere.</p>
<p>The provider layer sequences the hardening steps to run in the correct order for each provider — specifically, it waits for network availability before applying network-level hardening, and ensures the package manager is configured before running Ansible roles that require package installation.</p>
<p><strong>Metadata endpoint configuration:</strong></p>
<p>CIS controls include restrictions on access to the instance metadata service (IMDSv2 enforcement on AWS, equivalent controls on GCP/Azure). The provider layer applies the correct restriction for each cloud — the blueprint just declares <code class="" data-line="">compliance: benchmark: cis-l1</code>.</p>
<hr />
<h2 id="building-every-provider">Building Every Provider</h2>
<p>There is no built-in fan-out flag, and honestly none is needed — the CLI is exit-code shaped,<br />
so the shell already does this well:</p>
<pre><code class="" data-line=""># Validate everything first; stop before spending money if anything is wrong
bakex validate blueprints/ubuntu/22.04/*.yaml || exit 1

# Then build each target
for bp in blueprints/ubuntu/22.04/cis-l1-*.yaml; do
  bakex build &quot;$bp&quot; --json &gt; &quot;builds/$(basename &quot;$bp&quot; .yaml).json&quot; &amp;
done
wait
</code></pre>
<p><code class="" data-line="">--json</code> emits the job record — id, profile name, provider, status, artifact ID, error — which<br />
is what you want when six builds are writing to six files at once. Every build either lands a<br />
<code class="" data-line="">complete</code> status with an artifact ID, or a <code class="" data-line="">failed</code> status with the reason. Nothing produces<br />
a half-hardened image.</p>
<p>The validate-then-build ordering matters more than it looks. Validation is offline and takes<br />
milliseconds; a build takes 15–25 minutes and costs money. Catching a malformed blueprint or an<br />
unsupported OS/provider pair in the first step means you never launch the instance.</p>
<hr />
<h2 id="blueprint-versioning-and-drift">Blueprint Versioning and Drift</h2>
<p>Version-controlling the blueprint file solves a problem multi-cloud environments hit<br />
consistently: knowing what your OS security posture was six months ago. The blueprint is the<br />
answer — it&#8217;s a file, in git, with a commit history and a reviewer&#8217;s name on every change.</p>
<p>Re-scanning a <em>running</em> instance against the posture that built it is a separate job, and it<br />
does not live in the CLI. <code class="" data-line="">bakex validate</code> and <code class="" data-line="">bakex build</code> are the two CLI verbs; scanning<br />
and drift comparison are in the web UI and the HTTP API, where the scan results have somewhere<br />
to live. EP04 covers that surface in detail — the A–F grade, the SARIF export, and comparing a<br />
current scan against a stored baseline.</p>
<p>The useful discipline in the meantime is unglamorous: rebuild from the blueprint rather than<br />
patching running instances. An instance that drifted is a symptom; the blueprint is the cure,<br />
and re-baking is cheaper than reconciling.</p>
<hr />
<h2 id="production-gotchas">Production Gotchas</h2>
<p><strong>Provider-specific CIS controls exist.</strong> CIS AWS Foundations Benchmark and CIS GCP Benchmark include cloud-specific controls (VPC flow logs, CloudTrail, etc.) that are separate from the OS-level CIS controls. The blueprint handles OS-level controls. Cloud-level controls (IAM, logging, network configuration) belong in your cloud security posture management tooling.</p>
<p><strong>Build costs vary by provider.</strong> On AWS, the build instance is a <code class="" data-line="">t3.medium</code> for 15–20 minutes (~$0.02). On GCP and Azure, equivalent pricing applies. For multi-provider builds, run them in regions close to your primary workloads to minimize image transfer time.</p>
<p><strong>Proxmox is a template VMID, not an image name.</strong> Every cloud provider names its base image with a string; Proxmox names it with a number — the VE template&#8217;s VMID (<code class="" data-line="">9000</code> in the shipped blueprint). The provider talks to the Proxmox API remotely via <code class="" data-line="">proxmoxer</code>, so no agent on the host is required, but it does need <code class="" data-line="">host</code> credentials and it discovers the built VM&#8217;s IP through the QEMU guest agent <em>inside</em> the VM. If the guest agent isn&#8217;t installed in your template, the build will provision and then hang waiting for an address.</p>
<p><strong>KVM and Proxmox are deliberately different providers.</strong> They look interchangeable and aren&#8217;t: a KVM target names a downloadable cloud image, a Proxmox target names a VE template that already exists on your host. Don&#8217;t assume a blueprint written for one works on the other.</p>
<p><strong>GCP image sharing across projects requires explicit IAM.</strong> GCP machine images aren&#8217;t automatically available to other projects in the organization. BakeX builds the image; sharing it is a GCP IAM operation you configure at the project or organization level — there&#8217;s no BakeX command that grants cross-project access for you.</p>
<hr />
<h2 id="key-takeaways">Key Takeaways</h2>
<ul>
<li>Multi-cloud OS hardening with separate scripts per provider creates inevitable drift; a provider-abstracted blueprint eliminates it</li>
<li>BakeX ships working blueprints for AWS, GCP, Azure, DigitalOcean, Linode, and Proxmox — one file per provider, with <code class="" data-line="">target</code> as the only section that differs</li>
<li>The provider is a field in the blueprint, not a CLI flag: every file is self-describing and builds identically in CI, locally, or on a teammate&#8217;s machine</li>
<li>Fan-out is a shell loop over exit codes, not a framework feature — validate all six offline first, then build in parallel with <code class="" data-line="">--json</code></li>
<li>Blueprint version control is the single source of truth for OS security posture history — and a compliance change that isn&#8217;t identical across all six providers shows up as an odd hunk in code review</li>
</ul>
<hr />
<h2 id="whats-next">What&#8217;s Next</h2>
<p>Six providers, one compliance posture, and a diff that proves it. EP03 showed that the multi-cloud drift problem disappears when provider details are confined to a single block of the blueprint.</p>
<p>What neither EP02 nor EP03 answered is the auditor&#8217;s question: how do you know the image is actually compliant? &#8220;We ran CIS L1&#8221; is not an answer. &#8220;Grade A, 98/100 controls, SARIF export attached&#8221; is.</p>
<p>EP04 covers automated OpenSCAP compliance: the post-build scan in detail — how the A-F grade is calculated, what controls block an A grade, how SARIF exports work, and how drift detection catches what changed after deployment.</p>
<p><em>Next: <a href="/automated-compliance-scanning-openscap/">automated OpenSCAP compliance — CIS benchmark grading before deployment</a></em></p>
<p>Get EP04 in your inbox when it publishes → <a href="https://linuxcent.com/subscribe">linuxcent.com/subscribe</a></p>
<p><a class="a2a_button_mastodon" href="https://www.addtoany.com/add_to/mastodon?linkurl=https%3A%2F%2Flinuxcent.com%2Flinux-hardening-multi-cloud%2F&amp;linkname=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" 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%2Flinux-hardening-multi-cloud%2F&amp;linkname=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" 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%2Flinux-hardening-multi-cloud%2F&amp;linkname=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" 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%2Flinux-hardening-multi-cloud%2F&amp;linkname=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" 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%2Flinux-hardening-multi-cloud%2F&amp;linkname=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" 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%2Flinux-hardening-multi-cloud%2F&amp;linkname=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" 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%2Flinux-hardening-multi-cloud%2F&amp;linkname=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" 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%2Flinux-hardening-multi-cloud%2F&#038;title=One%20Blueprint%2C%20Six%20Clouds%20%E2%80%94%20Multi-Provider%20OS%20Image%20Builds" data-a2a-url="https://linuxcent.com/linux-hardening-multi-cloud/" data-a2a-title="One Blueprint, Six Clouds — Multi-Provider OS Image Builds"></a></p><p>The post <a href="https://linuxcent.com/linux-hardening-multi-cloud/">One Blueprint, Six Clouds — Multi-Provider OS Image Builds</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://linuxcent.com/linux-hardening-multi-cloud/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1774</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-31 09:37:11 by W3 Total Cache
-->