<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: francotel</title>
    <description>The latest articles on Forem by francotel (@francotel).</description>
    <link>https://forem.com/francotel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F349403%2F849c9efc-abad-4ba0-b34f-678403390dfd.png</url>
      <title>Forem: francotel</title>
      <link>https://forem.com/francotel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/francotel"/>
    <language>en</language>
    <item>
      <title>Building a Secure Serverless Upload Pattern on AWS with Terraform 🚀</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Sun, 08 Mar 2026 17:09:57 +0000</pubDate>
      <link>https://forem.com/francotel/building-a-secure-serverless-upload-pattern-on-aws-with-terraform-40f2</link>
      <guid>https://forem.com/francotel/building-a-secure-serverless-upload-pattern-on-aws-with-terraform-40f2</guid>
      <description>&lt;h2&gt;
  
  
  𝗗𝗶𝗿𝗲𝗰𝘁 𝘂𝗽𝗹𝗼𝗮𝗱𝘀. 𝗭𝗲𝗿𝗼 𝗯𝗮𝗰𝗸𝗲𝗻𝗱 𝗯𝗼𝘁𝘁𝗹𝗲𝗻𝗲𝗰𝗸𝘀. 𝗘𝗻𝘁𝗲𝗿𝗽𝗿𝗶𝘀𝗲-𝗴𝗿𝗮𝗱𝗲 𝘀𝗲𝗰𝘂𝗿𝗶𝘁𝘆.
&lt;/h2&gt;

&lt;p&gt;🧠 𝗔 𝗥𝗲𝗮𝗹-𝗪𝗼𝗿𝗹𝗱 𝗣𝗿𝗼𝗯𝗹𝗲𝗺 (𝗧𝗵𝗮𝘁 𝗜 𝗞𝗲𝗲𝗽 𝗦𝗲𝗲𝗶𝗻𝗴)&lt;/p&gt;

&lt;p&gt;A few weeks ago, I was reviewing a system where users were uploading files (some &amp;gt;300MB).&lt;/p&gt;

&lt;p&gt;The original flow looked “reasonable”:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Frontend uploads the file to the backend&lt;/li&gt;
&lt;li&gt;Backend processes the request&lt;/li&gt;
&lt;li&gt;Backend uploads the file to S3&lt;/li&gt;
&lt;li&gt;Backend responds&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But in practice, the system was 𝗳𝗮𝗹𝗹𝗶𝗻𝗴 𝗮𝗽𝗮𝗿𝘁:&lt;/p&gt;

&lt;p&gt;❌ Timeouts&lt;br&gt;
❌ Lambda memory spikes&lt;br&gt;
❌ High AWS bills&lt;br&gt;
❌ Angry users&lt;/p&gt;

&lt;p&gt;And the root cause was always the same:&lt;/p&gt;

&lt;p&gt;𝗧𝗵𝗲 𝗯𝗮𝗰𝗸𝗲𝗻𝗱 𝘀𝗵𝗼𝘂𝗹𝗱 𝗡𝗘𝗩𝗘𝗥 𝗵𝗮𝗻𝗱𝗹𝗲 𝗳𝗶𝗹𝗲 𝘂𝗽𝗹𝗼𝗮𝗱𝘀 𝗶𝗻 𝗮 𝘀𝗲𝗿𝘃𝗲𝗿𝗹𝗲𝘀𝘀 𝗮𝗿𝗰𝗵𝗶𝘁𝗲𝗰𝘁𝘂𝗿𝗲.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExMm15NWoxYzdidDczN2MyZGVsYmZpdWxoZjUxMW03ZW16ZjY0aGk0ZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FKajpERDjOpMcw%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExMm15NWoxYzdidDczN2MyZGVsYmZpdWxoZjUxMW03ZW16ZjY0aGk0ZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FKajpERDjOpMcw%2Fgiphy.gif" width="480" height="268"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;💡 𝗧𝗵𝗲 𝗣𝗮𝘁𝘁𝗲𝗿𝗻 𝗧𝗵𝗮𝘁 𝗙𝗶𝘅𝗲𝘀 𝗘𝘃𝗲𝗿𝘆𝘁𝗵𝗶𝗻𝗴&lt;br&gt;
The solution is a 𝘄𝗲𝗹𝗹-𝗸𝗻𝗼𝘄𝗻 𝗯𝘂𝘁 𝗼𝗳𝘁𝗲𝗻 𝗺𝗶𝘀𝘂𝘀𝗲𝗱 𝗽𝗮𝘁𝘁𝗲𝗿𝗻:&lt;/p&gt;

&lt;p&gt;👉 𝗦𝟯 𝗣𝗿𝗲𝘀𝗶𝗴𝗻𝗲𝗱 𝗨𝗥𝗟𝘀&lt;/p&gt;

&lt;p&gt;Instead of uploading files 𝘵𝘩𝘳𝘰𝘶𝘨𝘩 your backend, you let the client upload 𝗱𝗶𝗿𝗲𝗰𝘁𝗹𝘆 𝘁𝗼 𝗦𝟯, but in a 𝗰𝗼𝗻𝘁𝗿𝗼𝗹𝗹𝗲𝗱, 𝘁𝗲𝗺𝗽𝗼𝗿𝗮𝗿𝘆, 𝗮𝗻𝗱 𝘀𝗲𝗰𝘂𝗿𝗲 𝘄𝗮𝘆.&lt;/p&gt;

&lt;p&gt;This is the same pattern used by:&lt;br&gt;
● Fintech platforms&lt;br&gt;
● Healthcare systems&lt;br&gt;
● Large SaaS products&lt;/p&gt;



&lt;p&gt;🧩 𝗛𝗼𝘄 𝘁𝗵𝗲 𝗔𝗿𝗰𝗵𝗶𝘁𝗲𝗰𝘁𝘂𝗿𝗲 𝗪𝗼𝗿𝗸𝘀&lt;br&gt;
𝗛𝗶𝗴𝗵-𝗹𝗲𝘃𝗲𝗹 𝗳𝗹𝗼𝘄:&lt;/p&gt;

&lt;p&gt;1️⃣ Client asks permission to upload a file&lt;br&gt;
2️⃣ API Gateway → Lambda generates a 𝗣𝗿𝗲𝘀𝗶𝗴𝗻𝗲𝗱 𝗨𝗥𝗟&lt;br&gt;
3️⃣ Client uploads 𝗱𝗶𝗿𝗲𝗰𝘁𝗹𝘆 𝘁𝗼 𝗦𝟯 using PUT&lt;br&gt;
4️⃣ Backend never touches the file&lt;/p&gt;

&lt;p&gt;🎯 Result:&lt;br&gt;
● Zero bottlenecks&lt;br&gt;
● Minimal Lambda execution time&lt;br&gt;
● Lower cost&lt;br&gt;
● Better UX&lt;/p&gt;



&lt;p&gt;🔐 𝗪𝗵𝗮𝘁 𝗜𝘀 𝗮 𝗣𝗿𝗲𝘀𝗶𝗴𝗻𝗲𝗱 𝗨𝗥𝗟 (𝗜𝗻 𝗦𝗶𝗺𝗽𝗹𝗲 𝗧𝗲𝗿𝗺𝘀)?&lt;/p&gt;

&lt;p&gt;Think of a presigned URL as:&lt;br&gt;
🎟️ 𝗔 𝘁𝗲𝗺𝗽𝗼𝗿𝗮𝗿𝘆, 𝘀𝗶𝗻𝗴𝗹𝗲-𝗽𝘂𝗿𝗽𝗼𝘀𝗲 𝘁𝗶𝗰𝗸𝗲𝘁&lt;br&gt;
● Valid only for a few minutes&lt;br&gt;
● Allows only one specific action (e.g. PUT)&lt;br&gt;
● Scoped to a single object&lt;br&gt;
● No AWS credentials exposed&lt;/p&gt;

&lt;p&gt;Once it expires → 𝗶𝘁’𝘀 𝘂𝘀𝗲𝗹𝗲𝘀𝘀.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8shr36ouc6jkhtxmoz6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8shr36ouc6jkhtxmoz6.gif" width="980" height="772"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;⚙️ 𝗟𝗮𝗺𝗯𝗱𝗮: 𝗚𝗲𝗻𝗲𝗿𝗮𝘁𝗶𝗻𝗴 𝘁𝗵𝗲 𝗣𝗿𝗲𝘀𝗶𝗴𝗻𝗲𝗱 𝗨𝗥𝗟 (𝗡𝗼𝗱𝗲.𝗷𝘀)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PutObjectCommand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-s3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getSignedUrl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/s3-request-presigner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PutObjectCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUCKET_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uploadUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSignedUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 5 minutes&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;uploadUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbnwzjzve2tqky27r2h5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbnwzjzve2tqky27r2h5.png" alt="flow-request" width="800" height="840"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[!WARNING]&lt;br&gt;
&lt;strong&gt;⚠️ 𝗜𝗺𝗽𝗼𝗿𝘁𝗮𝗻𝘁:&lt;/strong&gt;&lt;br&gt;
The Lambda never sees the file, it only authorizes the upload.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;🛡️ 𝗦𝗲𝗰𝘂𝗿𝗶𝘁𝘆 𝗟𝗮𝘆𝗲𝗿𝘀 (𝗪𝗵𝗮𝘁 𝗠𝗮𝗸𝗲𝘀 𝗧𝗵𝗶𝘀 𝗣𝗿𝗼𝗱𝘂𝗰𝘁𝗶𝗼𝗻-𝗥𝗲𝗮𝗱𝘆)&lt;/p&gt;

&lt;p&gt;This PoC follows 𝗿𝗲𝗮𝗹 𝗲𝗻𝘁𝗲𝗿𝗽𝗿𝗶𝘀𝗲 𝗽𝗿𝗮𝗰𝘁𝗶𝗰𝗲𝘀, not just demos.&lt;/p&gt;

&lt;p&gt;🔐 𝟭. 𝗦𝗵𝗼𝗿𝘁-𝗹𝗶𝘃𝗲𝗱 𝗨𝗥𝗟𝘀&lt;br&gt;
● 5–10 minutes max&lt;br&gt;
● Enough for upload, useless afterward&lt;/p&gt;

&lt;p&gt;🔐 𝟮. 𝗜𝗔𝗠 𝗟𝗲𝗮𝘀𝘁 𝗣𝗿𝗶𝘃𝗶𝗹𝗲𝗴𝗲&lt;/p&gt;

&lt;p&gt;Lambda role can 𝗼𝗻𝗹𝘆 do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::my-bucket/uploads/*"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing else.&lt;/p&gt;

&lt;p&gt;🔐 𝟯. 𝗣𝗿𝗶𝘃𝗮𝘁𝗲 𝗦𝟯 𝗕𝘂𝗰𝗸𝗲𝘁&lt;br&gt;
● No public access&lt;br&gt;
● No ACL tricks&lt;br&gt;
● Only presigned URLs work&lt;/p&gt;

&lt;p&gt;🔐 𝟰. 𝗦𝗮𝗻𝗶𝘁𝗶𝘇𝗲𝗱 𝗢𝗯𝗷𝗲𝗰𝘁 𝗡𝗮𝗺𝗲𝘀&lt;br&gt;
● UUID-based keys&lt;br&gt;
● No user-controlled paths&lt;br&gt;
● No path traversal risks&lt;/p&gt;

&lt;p&gt;🔐 𝟱. 𝗖𝗢𝗥𝗦 𝗖𝗼𝗿𝗿𝗲𝗰𝘁𝗹𝘆 𝗖𝗼𝗻𝗳𝗶𝗴𝘂𝗿𝗲𝗱&lt;/p&gt;

&lt;p&gt;Because 𝗖𝗢𝗥𝗦 𝗶𝘀 𝗮𝗹𝘄𝗮𝘆𝘀 𝘁𝗵𝗲 𝗳𝗶𝗿𝘀𝘁 𝘁𝗵𝗶𝗻𝗴 𝘁𝗵𝗮𝘁 𝗯𝗿𝗲𝗮𝗸𝘀 😅&lt;/p&gt;



&lt;p&gt;🧱 𝗜𝗻𝗳𝗿𝗮𝘀𝘁𝗿𝘂𝗰𝘁𝘂𝗿𝗲 𝗮𝘀 𝗖𝗼𝗱𝗲 𝘄𝗶𝘁𝗵 𝗧𝗲𝗿𝗿𝗮𝗳𝗼𝗿𝗺&lt;/p&gt;

&lt;p&gt;Everything is deployed using 𝗧𝗲𝗿𝗿𝗮𝗳𝗼𝗿𝗺, so the architecture is:&lt;br&gt;
● Reproducible&lt;br&gt;
● Auditable&lt;br&gt;
● Ready for CI/CD&lt;/p&gt;

&lt;p&gt;Core components:&lt;br&gt;
● S3 bucket&lt;br&gt;
● Lambda&lt;br&gt;
● IAM roles&lt;br&gt;
● API Gateway (HTTP API)&lt;/p&gt;

&lt;p&gt;📌 𝘐𝘯 𝘵𝘩𝘦 𝘱𝘰𝘴𝘵 𝘐 𝘧𝘰𝘤𝘶𝘴 𝘰𝘯 𝘵𝘩𝘦 𝗮𝗿𝗰𝗵𝗶𝘁𝗲𝗰𝘁𝘂𝗿𝗲 𝗮𝗻𝗱 𝗽𝗮𝘁𝘁𝗲𝗿𝗻.&lt;br&gt;
𝘛𝘩𝘦 𝗳𝘂𝗹𝗹 𝗧𝗲𝗿𝗿𝗮𝗳𝗼𝗿𝗺 𝗶𝗺𝗽𝗹𝗲𝗺𝗲𝗻𝘁𝗮𝘁𝗶𝗼𝗻 𝘭𝘪𝘷𝘦𝘴 𝘪𝘯 𝘵𝘩𝘦 𝘳𝘦𝘱𝘰𝘴𝘪𝘵𝘰𝘳𝘺.&lt;/p&gt;



&lt;p&gt;📂 𝗥𝗲𝗽𝗼𝘀𝗶𝘁𝗼𝗿𝘆 𝗦𝘁𝗿𝘂𝗰𝘁𝘂𝗿𝗲 (𝗦𝗶𝗺𝗽𝗹𝗲 𝗯𝘆 𝗗𝗲𝘀𝗶𝗴𝗻)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;presigned&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tpl&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;png&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;png&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfvars&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;drawio&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;presignend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gif&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;drawio&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;png&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;png&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zip&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;Makefile&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;README&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;security&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;checkov&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;trivy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mjs&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfstate&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tfstate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backup&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;tfplan&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;tfplan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎯 Minimal, readable, and focused on the pattern.&lt;/p&gt;




&lt;p&gt;🧪 𝗥𝗲𝗾𝘂𝗶𝗿𝗲𝗺𝗲𝗻𝘁𝘀 𝘁𝗼 𝗥𝘂𝗻 𝘁𝗵𝗲 𝗣𝗼𝗖&lt;/p&gt;

&lt;p&gt;This PoC assumes:&lt;/p&gt;

&lt;p&gt;✅ macOS&lt;br&gt;
✅ Terraform already installed&lt;br&gt;
✅ AWS CLI already authenticated&lt;/p&gt;

&lt;p&gt;No extra setup. No magic.&lt;/p&gt;




&lt;p&gt;🚀 𝗪𝗮𝗻𝘁 𝘁𝗵𝗲 𝗙𝘂𝗹𝗹 𝗪𝗼𝗿𝗸𝗶𝗻𝗴 𝗣𝗼𝗖?&lt;/p&gt;

&lt;p&gt;I published the complete implementation here:&lt;/p&gt;

&lt;p&gt;👉 𝗵𝘁𝘁𝗽𝘀://𝗴𝗶𝘁𝗵𝘂𝗯.𝗰𝗼𝗺/𝗳𝗿𝗮𝗻𝗰𝗼𝘁𝗲𝗹/𝗮𝘄𝘀-𝘀𝟯-𝗽𝗿𝗲𝘀𝗶𝗴𝗻𝗲𝗱-𝘂𝗿𝗹-𝗹𝗮𝗺𝗯𝗱𝗮-𝘁𝗲𝗿𝗿𝗮𝗳𝗼𝗿𝗺 (𝗵𝘁𝘁𝗽𝘀://𝗴𝗶𝘁𝗵𝘂𝗯.𝗰𝗼𝗺/𝗳𝗿𝗮𝗻𝗰𝗼𝘁𝗲𝗹/𝗮𝘄𝘀-𝘀𝟯-𝗽𝗿𝗲𝘀𝗶𝗴𝗻𝗲𝗱-𝘂𝗿𝗹-𝗹𝗮𝗺𝗯𝗱𝗮-𝘁𝗲𝗿𝗿𝗮𝗳𝗼𝗿𝗺)&lt;/p&gt;

&lt;p&gt;You’ll find:&lt;br&gt;
● Full Terraform code&lt;br&gt;
● Lambda (Node.js 20)&lt;br&gt;
● Test scripts&lt;br&gt;
● Architecture diagram&lt;/p&gt;

&lt;p&gt;Clone it, deploy it, break it, improve it.&lt;/p&gt;




&lt;p&gt;🎯 𝗙𝗶𝗻𝗮𝗹 𝗧𝗵𝗼𝘂𝗴𝗵𝘁&lt;/p&gt;

&lt;p&gt;If your backend is still handling file uploads, you’re paying more 𝗮𝗻𝗱 scaling less.&lt;/p&gt;

&lt;p&gt;This pattern:&lt;br&gt;
● Reduces cost&lt;br&gt;
● Improves reliability&lt;br&gt;
● Scales naturally&lt;br&gt;
● Matches real-world cloud architectures&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcHY3N2pqMHlmZG15aGJjdG8xdW5kNnVpOTh0c2hrN2ViZXZ2endvdyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2Fkd9BlRovbPOykLBMqX%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcHY3N2pqMHlmZG15aGJjdG8xdW5kNnVpOTh0c2hrN2ViZXZ2endvdyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2Fkd9BlRovbPOykLBMqX%2Fgiphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyrnid303a4yvtnx28d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyrnid303a4yvtnx28d6.png" alt="demo" width="800" height="1005"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspiration and References
&lt;/h3&gt;

&lt;p&gt;This project was inspired by the AWS blog post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Securing Amazon S3 presigned URLs for serverless applications
&lt;a href="https://aws.amazon.com/blogs/compute/securing-amazon-s3-presigned-urls-for-serverless-applications/" rel="noopener noreferrer"&gt;https://aws.amazon.com/blogs/compute/securing-amazon-s3-presigned-urls-for-serverless-applications/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;The article explores several best practices &lt;span class="k"&gt;for &lt;/span&gt;securing presigned
URLs &lt;span class="k"&gt;in &lt;/span&gt;serverless architectures, including checksum validation,
expiration strategies, and least-privilege IAM policies.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>terraform</category>
      <category>crosscloudx</category>
    </item>
    <item>
      <title>NestJS in Production: 20 Default Configurations That Can Break Your Kubernetes Cluster (A DevOps Story)</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Thu, 26 Feb 2026 02:15:16 +0000</pubDate>
      <link>https://forem.com/francotel/nestjs-in-production-20-default-configurations-that-can-break-your-kubernetes-cluster-a-devops-3d2g</link>
      <guid>https://forem.com/francotel/nestjs-in-production-20-default-configurations-that-can-break-your-kubernetes-cluster-a-devops-3d2g</guid>
      <description>&lt;h3&gt;
  
  
  😱 Production went down… because of a default setting
&lt;/h3&gt;

&lt;p&gt;Have you ever seen this?&lt;/p&gt;

&lt;p&gt;The dev team ships a new feature using a modern, elegant, &lt;strong&gt;enterprise-ready&lt;/strong&gt; framework like &lt;strong&gt;NestJS&lt;/strong&gt;.Everything works perfectly on local.QA passes.Production deploys.&lt;/p&gt;

&lt;p&gt;And suddenly…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  500 errors everywhere&lt;/li&gt;
&lt;li&gt;  Kubernetes pods restarting&lt;/li&gt;
&lt;li&gt;  Logs that tell you absolutely nothing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The root cause?&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;A 100kb default request body limit that nobody knew existed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. That &lt;em&gt;tiny&lt;/em&gt; default almost ruined our Friday night. 😅&lt;/p&gt;

&lt;p&gt;As a DevOps engineer working with Kubernetes and Azure, this was a wake-up call. NestJS is an amazing framework—but &lt;strong&gt;defaults are not production-ready by magic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This post is not about blaming developers.It’s about &lt;strong&gt;shared responsibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Framework defaults are convenient.Production environments are not.&lt;/p&gt;

&lt;p&gt;Below are &lt;strong&gt;20 NestJS defaults and behaviors that every DevOps engineer should be aware of when NestJS lands in a Kubernetes cluster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExZThkeHJ0dmdzYWl2OG1va3JvMGl1aWM3OWYzcHNza3IwMXdvcmR4bSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F1LYS8RmnsFwg8%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExZThkeHJ0dmdzYWl2OG1va3JvMGl1aWM3OWYzcHNza3IwMXdvcmR4bSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F1LYS8RmnsFwg8%2Fgiphy.gif" width="468" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣ The 100kb That Almost Killed PROD (Body Parser)
&lt;/h2&gt;

&lt;p&gt;NestJS (with Express under the hood) uses body-parser.By default, it only accepts &lt;strong&gt;100kb&lt;/strong&gt; for JSON payloads.&lt;/p&gt;

&lt;p&gt;If your API handles file uploads, base64 payloads, or large requests, you’ll get a PayloadTooLargeError that often becomes a silent 500.&lt;/p&gt;

&lt;p&gt;👉 Fix it explicitly in main.ts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10mb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; defaults are optimized for demos, not real traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  2️⃣ HTTP Timeouts Are Not Infinite
&lt;/h2&gt;

&lt;p&gt;Node’s HTTP server does not wait forever.&lt;/p&gt;

&lt;p&gt;Long-running requests, slow downstream services, or blocked connections can slowly exhaust your pod resources.&lt;/p&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  server.timeout&lt;/li&gt;
&lt;li&gt;  keepAliveTimeout&lt;/li&gt;
&lt;li&gt;  Or enforce limits at the Ingress / Load Balancer level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DevOps takeaway:&lt;/strong&gt; timeouts are part of capacity planning.&lt;/p&gt;

&lt;h2&gt;
  
  
  3️⃣ The Logger That Doesn’t Log (in Production)
&lt;/h2&gt;

&lt;p&gt;console.log is fine… until it isn’t.&lt;/p&gt;

&lt;p&gt;In production you want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Structured logs (JSON)&lt;/li&gt;
&lt;li&gt;  Correlation IDs&lt;/li&gt;
&lt;li&gt;  Compatibility with ELK, Datadog, Azure Monitor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use app.useLogger() with &lt;strong&gt;pino&lt;/strong&gt; or &lt;strong&gt;winston&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Logs are not for developers.They are for &lt;strong&gt;incident response&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4️⃣ Shutdown Hooks: Kubernetes Is Not Polite
&lt;/h2&gt;

&lt;p&gt;When Kubernetes terminates a pod, it sends SIGTERM.&lt;br&gt;
If your app ignores it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In-flight requests are dropped&lt;/li&gt;
&lt;li&gt;  Users see 5xx errors&lt;/li&gt;
&lt;li&gt;  You lose trust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enable graceful shutdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enableShutdownHooks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And drain traffic properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  5️⃣ Environment Variables: .env Is Not Production
&lt;/h2&gt;

&lt;p&gt;@nestjs/config looks for .env files by default.&lt;/p&gt;

&lt;p&gt;In Kubernetes, configuration comes from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Environment variables&lt;/li&gt;
&lt;li&gt;  ConfigMaps&lt;/li&gt;
&lt;li&gt;  Secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid filesystem dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;ConfigModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  &lt;span class="na"&gt;ignoreEnvFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6️⃣ Global Modules: Convenience vs Control
&lt;/h2&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/global"&gt;@global&lt;/a&gt;() modules feel nice.&lt;/p&gt;

&lt;p&gt;They also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Hide dependencies&lt;/li&gt;
&lt;li&gt;  Increase coupling&lt;/li&gt;
&lt;li&gt;  Complicate testing&lt;/li&gt;
&lt;li&gt;  Make scaling harder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What’s convenient for development can be painful in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  7️⃣ Dependency Injection Can Betray You
&lt;/h2&gt;

&lt;p&gt;Custom providers and factories can introduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Circular dependencies&lt;/li&gt;
&lt;li&gt;  Runtime undefined errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These issues often appear &lt;strong&gt;only under load&lt;/strong&gt;.&lt;br&gt;
Use dependency graphs and be suspicious of “magic”.&lt;/p&gt;
&lt;h2&gt;
  
  
  8️⃣ Global Exception Filters Are Mandatory
&lt;/h2&gt;

&lt;p&gt;Without a global exception filter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Errors are inconsistent&lt;/li&gt;
&lt;li&gt;  Stack traces may leak&lt;/li&gt;
&lt;li&gt;  Logs are unstructured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Always normalize errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useGlobalFilters&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Predictable errors = predictable operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  9️⃣ Guards Can Kill Performance
&lt;/h2&gt;

&lt;p&gt;Guards run &lt;strong&gt;before&lt;/strong&gt; interceptors and pipes.&lt;br&gt;
Heavy logic here (rate limiting, DB calls) affects &lt;strong&gt;every request&lt;/strong&gt;.&lt;br&gt;
Security ≠ expensive execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔟 Shipping start:dev to Kubernetes (Yes, It Happens)
&lt;/h2&gt;

&lt;p&gt;Always:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Build with npm run build&lt;/li&gt;
&lt;li&gt;  Run node dist/main.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Otherwise you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Huge images&lt;/li&gt;
&lt;li&gt;  Dev dependencies in prod&lt;/li&gt;
&lt;li&gt;  Slower startups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve seen &lt;strong&gt;2GB images&lt;/strong&gt; because of this.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣1️⃣ CacheModule Is Not Shared
&lt;/h2&gt;

&lt;p&gt;In-memory cache:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Is pod-local&lt;/li&gt;
&lt;li&gt;  Is volatile&lt;/li&gt;
&lt;li&gt;  Breaks consistency in clusters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For real workloads, use Redis or another external store.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣2️⃣ Scheduled Tasks Can Block the Event Loop
&lt;/h2&gt;

&lt;p&gt;@nestjs/schedule runs inside the same process.&lt;/p&gt;

&lt;p&gt;Long-running jobs = slower APIs.&lt;/p&gt;

&lt;p&gt;Move heavy work out or make it truly async.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣3️⃣ Correlation Headers Belong to Middleware
&lt;/h2&gt;

&lt;p&gt;Headers like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  X-Request-ID&lt;/li&gt;
&lt;li&gt;  X-Correlation-ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Global&lt;/li&gt;
&lt;li&gt;  Mandatory&lt;/li&gt;
&lt;li&gt;  Documented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not copy-pasted across controllers.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣4️⃣ Health Checks Must Be Honest
&lt;/h2&gt;

&lt;p&gt;Kubernetes doesn’t care if port 3000 responds.&lt;/p&gt;

&lt;p&gt;It cares if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  DB is reachable&lt;/li&gt;
&lt;li&gt;  Queues are alive&lt;/li&gt;
&lt;li&gt;  Dependencies are healthy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Liveness ≠ Readiness.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣5️⃣ Response Size Is a Memory Problem
&lt;/h2&gt;

&lt;p&gt;Large payloads = memory pressure.&lt;/p&gt;

&lt;p&gt;Pagination is not optional.It’s a survival mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣6️⃣ API Versioning Is a Day-One Decision
&lt;/h2&gt;

&lt;p&gt;No versioning = broken clients later.&lt;/p&gt;

&lt;p&gt;NestJS supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  URI versioning&lt;/li&gt;
&lt;li&gt;  Header versioning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pick one early.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣7️⃣ WebSockets Don’t Scale by Default
&lt;/h2&gt;

&lt;p&gt;WebSocket connections stick to a pod.&lt;/p&gt;

&lt;p&gt;For horizontal scaling, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Redis adapters&lt;/li&gt;
&lt;li&gt;  Message brokers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stateful connections break stateless assumptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣8️⃣ Database Connection Pools Matter
&lt;/h2&gt;

&lt;p&gt;Default pool sizes are usually small.&lt;/p&gt;

&lt;p&gt;Multiply that by pod replicas and you’ll hit DB limits fast.&lt;/p&gt;

&lt;p&gt;Tune pools intentionally.&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣9️⃣ Axios Has No Timeout (Yes, Really)
&lt;/h2&gt;

&lt;p&gt;NestJS HttpModule uses Axios.&lt;br&gt;
Axios defaults:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;No timeout&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One hanging dependency can block your service forever.&lt;/p&gt;

&lt;p&gt;Always set timeouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  2️⃣0️⃣ Swagger Is Not Decoration
&lt;/h2&gt;

&lt;p&gt;Outdated Swagger docs cause:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Misuse&lt;/li&gt;
&lt;li&gt;  Invalid payloads&lt;/li&gt;
&lt;li&gt;  Production incidents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Automate updates. Treat docs as code.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thought: DevOps Is Not Just YAML
&lt;/h2&gt;

&lt;p&gt;NestJS is &lt;strong&gt;enterprise-ready&lt;/strong&gt;, but enterprises are messy.&lt;/p&gt;

&lt;p&gt;Scalability doesn’t come from frameworks alone.It comes from &lt;strong&gt;Dev and Ops understanding how software behaves under pressure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So next time NestJS lands in your cluster, don’t just review Kubernetes manifests.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Open main.ts.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It might save your weekend.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>devops</category>
      <category>nestjs</category>
      <category>crosscloudx</category>
      <category>k8s</category>
    </item>
    <item>
      <title>🧠 Cómo Sobrevivir a Múltiples Cuentas de GitHub sin Perder Tu Sanidad Mental (y Tu Trabajo)</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Wed, 18 Feb 2026 15:10:34 +0000</pubDate>
      <link>https://forem.com/francotel/como-sobrevivir-a-multiples-cuentas-de-github-sin-perder-tu-sanidad-mental-y-tu-trabajo-4lol</link>
      <guid>https://forem.com/francotel/como-sobrevivir-a-multiples-cuentas-de-github-sin-perder-tu-sanidad-mental-y-tu-trabajo-4lol</guid>
      <description>&lt;p&gt;🌅 𝗘𝗹 𝗠𝗼𝗺𝗲𝗻𝘁𝗼 𝗱𝗲𝗹 𝗣á𝗻𝗶𝗰𝗼: 𝟮 𝗔𝗠, 𝗩𝗶𝗲𝗿𝗻𝗲𝘀 𝗽𝗼𝗿 𝗹𝗮 𝗡𝗼𝗰𝗵𝗲&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;𝘨𝘪𝘵 𝘱𝘶𝘴𝘩 𝘰𝘳𝘪𝘨𝘪𝘯 𝘮𝘢𝘪𝘯
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;𝗘𝗥𝗥𝗢𝗥: 𝗣𝗲𝗿𝗺𝗶𝘀𝘀𝗶𝗼𝗻 𝗱𝗲𝗻𝗶𝗲𝗱 (𝗽𝘂𝗯𝗹𝗶𝗰𝗸𝗲𝘆). ❌&lt;/p&gt;

&lt;p&gt;Mi corazón se detuvo por 3 segundos.&lt;/p&gt;

&lt;p&gt;Eran las 2 de la madrugada. Mi jefe necesitaba el &lt;em&gt;hotfix&lt;/em&gt; para la demo con el cliente en Asia en 6 horas. Y yo, desde mi laptop personal, estaba viendo cómo el universo conspiraba contra mi fin de semana.&lt;/p&gt;

&lt;p&gt;El problema: 𝗚𝗶𝘁𝗛𝘂𝗯 𝗻𝗼 𝘀𝗮𝗯í𝗮 𝘀𝗶 𝗲𝗿𝗮 "𝗗𝗲𝘃 𝗣𝗲𝗿𝘀𝗼𝗻𝗮𝗹" 𝗼 "𝗗𝗲𝘃 𝗖𝗼𝗿𝗽𝗼𝗿𝗮𝘁𝗶𝘃𝗼". Y estaba usando la identidad equivocada.&lt;/p&gt;

&lt;p&gt;𝘚𝘶𝘦𝘯𝘢 𝘧𝘢𝘮𝘪𝘭𝘪𝘢𝘳? 🥲&lt;/p&gt;

&lt;p&gt;Si alguna vez has:&lt;br&gt;
● Trabajado en una startup y tenido tu proyecto personal 🏠&lt;br&gt;
● Sido contratista para múltiples clientes 💼&lt;br&gt;
● Entrado a una empresa que te exige cuenta corporativa de GitHub 🏢&lt;br&gt;
● Tenido que hacer un commit urgente desde tu laptop personal 🔥&lt;/p&gt;

&lt;p&gt;...este post es para ti.&lt;/p&gt;



&lt;p&gt;📖 𝗟𝗮 𝗛𝗶𝘀𝘁𝗼𝗿𝗶𝗮 𝗥𝗲𝗮𝗹: 𝗖ó𝗺𝗼 𝘂𝗻𝗮 𝗘𝗺𝗽𝗿𝗲𝘀𝗮 𝗖𝗮𝘀𝗶 𝗣𝗶𝗲𝗿𝗱𝗲 𝘂𝗻 𝗖𝗹𝗶𝗲𝗻𝘁𝗲 𝗽𝗼𝗿 𝗦𝗦𝗛-𝗞𝗲𝘆𝘀 𝗠𝗮𝗹 𝗖𝗼𝗻𝗳𝗶𝗴𝘂𝗿𝗮𝗱𝗮𝘀&lt;/p&gt;

&lt;p&gt;Trabajo en 𝗧𝗲𝗰𝗵𝗖𝗼𝗿𝗽, una consultora que maneja proyectos para 15+ clientes diferentes. Cada cliente requiere:&lt;/p&gt;

&lt;p&gt;● Cuenta separada de GitHub 🔐&lt;br&gt;
● SSH-keys diferentes 🗝️&lt;br&gt;
● Repos privados aislados 📦&lt;/p&gt;

&lt;p&gt;𝗘𝗹 𝗰𝗮𝗼𝘀 𝗱𝗶𝗮𝗿𝗶𝗼:&lt;br&gt;
● Devs haciendo commits con identidad equivocada 😱&lt;br&gt;
● CI/CD pipelines fallando por permisos 🔥&lt;br&gt;
● 3 horas semanales de soporte técnico resolviendo estos problemas ⏰&lt;/p&gt;

&lt;p&gt;𝗘𝗹 𝗰𝗼𝘀𝘁𝗼: $15,000 USD/año en productividad perdida. 💸&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdf9z2axwsgf64afje1nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdf9z2axwsgf64afje1nw.png" alt="mul-keys" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎯 La Solución que Cambió Todo: Multi-SSH Keys como un Pro&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Paso 1: El Diagnóstico (Entendiendo el Problema)&lt;/p&gt;

&lt;p&gt;¿𝗤𝘂é 𝗸𝗲𝘆𝘀 𝘁𝗶𝗲𝗻𝗲𝘀 𝗮𝗰𝘁𝘂𝗮𝗹𝗺𝗲𝗻𝘁𝗲?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; ~/.ssh/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿𝗤𝘂é 𝘂𝘀𝘂𝗮𝗿𝗶𝗼 𝗲𝘀𝘁á 𝘂𝘀𝗮𝗻𝗱𝗼 𝗚𝗶𝘁 𝗮𝗵𝗼𝗿𝗮?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paso 2: La Cirugía - Crear Keys Separadas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 𝗞𝗲𝘆 𝗽𝗲𝗿𝘀𝗼𝗻𝗮𝗹 (𝗹𝗮 𝗾𝘂𝗲 𝘆𝗮 𝘁𝗶𝗲𝗻𝗲𝘀)&lt;/span&gt;
~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 𝗞𝗲𝘆 𝗽𝗮𝗿𝗮 𝗲𝗹 𝘁𝗿𝗮𝗯𝗮𝗷𝗼 𝗲𝗻 𝗙𝗶𝗻𝗧𝗲𝗰𝗵𝗖𝗼𝗿𝗽&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"tu@fintechcorp.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/fintech_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 𝗞𝗲𝘆 𝗽𝗮𝗿𝗮 𝗲𝗹 𝗰𝗹𝗶𝗲𝗻𝘁𝗲 𝗘-𝗰𝗼𝗺𝗺𝗲𝗿𝗰𝗲 &lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"tu@ecomcliente.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/ecom_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎨 Imagina que cada key es una llave física diferente para oficinas distintas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 3: El Archivo Mágico (~/.ssh/config)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 👤 𝗬𝗢 (𝗣𝗲𝗿𝘀𝗼𝗻𝗮𝗹) - 𝗠𝗶 𝗶𝗱𝗲𝗻𝘁𝗶𝗱𝗮𝗱 𝘀𝗲𝗰𝗿𝗲𝘁𝗮&lt;/span&gt;
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa
  AddKeysToAgent &lt;span class="nb"&gt;yes&lt;/span&gt;

&lt;span class="c"&gt;# 💼 𝗙𝗶𝗻𝗧𝗲𝗰𝗵𝗖𝗼𝗿𝗽 - 𝗠𝗶 𝘆𝗼 𝗰𝗼𝗿𝗽𝗼𝗿𝗮𝘁𝗶𝘃𝗼&lt;/span&gt;
Host github.com-fintech
  HostName github.com
  User git
  IdentityFile ~/.ssh/fintech_rsa
  AddKeysToAgent &lt;span class="nb"&gt;yes&lt;/span&gt;

&lt;span class="c"&gt;# 🛒 𝗘𝗰𝗼𝗺𝗖𝗹𝗶𝗲𝗻𝘁𝗲 - 𝗘𝗹 𝗽𝗿𝗼𝘆𝗲𝗰𝘁𝗼 𝗾𝘂𝗲 𝗽𝗮𝗴𝗮 𝗹𝗮𝘀 𝘃𝗮𝗰𝗮𝗰𝗶𝗼𝗻𝗲𝘀&lt;/span&gt;
Host github.com-ecom
  HostName github.com
  User git
  IdentityFile ~/.ssh/ecom_rsa
  AddKeysToAgent &lt;span class="nb"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Tip Pro: Piensa en esto como rutas de enrutamiento en una red compleja - cada host alias dirige el tráfico al destino correcto con las credenciales apropiadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 Paso 4: El Registro en GitHub (El Paso que Nadie Debe Saltarse)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Copia tu llave pública al portapapeles
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Para macOS (pbcopy)&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/ecom_rsa.pub | pbcopy

&lt;span class="c"&gt;# Para Linux (xclip)&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/ecom_rsa.pub | xclip &lt;span class="nt"&gt;-selection&lt;/span&gt; clipboard

&lt;span class="c"&gt;# Para Windows (PowerShell)&lt;/span&gt;
Get-Content ~/.ssh/ecom_rsa.pub | Set-Clipboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4.𝟮 𝗔𝗴𝗿é𝗴𝗮𝗹𝗮 𝗮 𝘁𝘂 𝗰𝘂𝗲𝗻𝘁𝗮 𝗱𝗲 𝗚𝗶𝘁𝗛𝘂𝗯&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ve a 𝗚𝗶𝘁𝗛𝘂𝗯.𝗰𝗼𝗺 (𝗵𝘁𝘁𝗽𝘀://𝗴𝗶𝘁𝗵𝘂𝗯.𝗰𝗼𝗺/) → 𝗦𝗲𝘁𝘁𝗶𝗻𝗴𝘀 (tu foto de perfil) ⚙️&lt;/li&gt;
&lt;li&gt;En el menú lateral, haz clic en "𝗦𝗦𝗛 𝗮𝗻𝗱 𝗚𝗣𝗚 𝗸𝗲𝘆𝘀" 🔑&lt;/li&gt;
&lt;li&gt;Haz clic en el botón verde "𝗡𝗲𝘄 𝗦𝗦𝗛 𝗸𝗲𝘆" o "𝗔𝗱𝗱 𝗦𝗦𝗛 𝗸𝗲𝘆" ➕&lt;/li&gt;
&lt;li&gt;En el formulario:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;𝗧𝗶𝘁𝗹𝗲: Un nombre descriptivo (ej: "MacBook Pro Work", "Personal Laptop", "Franco - Work")&lt;/li&gt;
&lt;li&gt;𝗞𝗲𝘆 𝘁𝘆𝗽𝗲: "Authentication Key" (mantén el default)&lt;/li&gt;
&lt;li&gt;𝗞𝗲𝘆: Pega el contenido de tu portapapeles (la llave pública)&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Haz clic en "𝗔𝗱𝗱 𝗦𝗦𝗛 𝗸𝗲𝘆" ✅&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mvrlm1is1sc0mtfb52x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mvrlm1is1sc0mtfb52x.png" alt="github-ssh" width="509" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 5: El Truco del Clonado Inteligente&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❌ 𝗔𝗻𝘁𝗲𝘀 &lt;span class="o"&gt;(&lt;/span&gt;𝗳𝗮𝗹𝗹𝗮𝗯𝗮 𝘀𝗶𝗲𝗺𝗽𝗿𝗲&lt;span class="o"&gt;)&lt;/span&gt;
git clone git@github.com:fintechcorp/proyecto-secreto.git

✅ 𝗗𝗲𝘀𝗽𝘂é𝘀 &lt;span class="o"&gt;(&lt;/span&gt;𝗳𝘂𝗻𝗰𝗶𝗼𝗻𝗮 𝗽𝗲𝗿𝗳𝗲𝗰𝘁𝗼&lt;span class="o"&gt;)&lt;/span&gt;
git clone git@github.com-fintech:fintechcorp/proyecto-secreto.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📊 𝗥𝗲𝘀𝘂𝗹𝘁𝗮𝗱𝗼𝘀 𝗥𝗲𝗮𝗹𝗲𝘀 𝗲𝗻 𝗺𝗶 𝗘𝗺𝗽𝗿𝗲𝘀𝗮 (𝗠é𝘁𝗿𝗶𝗰𝗮 𝗾𝘂𝗲 𝗜𝗺𝗽𝗼𝗿𝘁𝗮)&lt;/p&gt;

&lt;p&gt;𝗔𝗻𝘁𝗲𝘀 𝗱𝗲 𝗹𝗮 𝗶𝗺𝗽𝗹𝗲𝗺𝗲𝗻𝘁𝗮𝗰𝗶ó𝗻 (𝗘𝗻𝗲 𝟮𝟬𝟮𝟱):&lt;br&gt;
🔴 12 incidentes/mes por credenciales incorrectas&lt;br&gt;
🔴 8 horas/mes de soporte DevOps&lt;br&gt;
🔴 3 devs frustrados renunciaron (ok, esto no fue solo por SSH, pero ayudó)&lt;/p&gt;

&lt;p&gt;𝗗𝗲𝘀𝗽𝘂é𝘀 (𝗝𝘂𝗻 𝟮𝟬𝟮𝟱):&lt;br&gt;
🟢 0 incidentes por credenciales&lt;br&gt;
🟢 0 horas de soporte (autogestionado)&lt;br&gt;
🟢 Devs pueden cambiar de contexto en &amp;lt;1 minuto&lt;/p&gt;

&lt;p&gt;𝗜𝗺𝗽𝗮𝗰𝘁𝗼 𝗳𝗶𝗻𝗮𝗻𝗰𝗶𝗲𝗿𝗼:&lt;/p&gt;

&lt;p&gt;"𝘈𝘩𝘰𝘳𝘳𝘢𝘮𝘰𝘴 $12,000 𝘢𝘭 𝘢ñ𝘰 𝘴𝘰𝘭𝘰 𝘦𝘯 𝘵𝘪𝘦𝘮𝘱𝘰 𝘥𝘦 𝘵𝘳𝘰𝘶𝘣𝘭𝘦𝘴𝘩𝘰𝘰𝘵𝘪𝘯𝘨" - 𝘊𝘛𝘖 𝘥𝘦 𝘛𝘦𝘤𝘩𝘊𝘰𝘳𝘱&lt;/p&gt;
&lt;h3&gt;
  
  
  🎮 Bonus: El Debugging Mode (Cuando Algo Sale Mal)
&lt;/h3&gt;

&lt;p&gt;Comandos de Diagnóstico Rápido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ¿𝗤𝘂é 𝗸𝗲𝘆 𝗲𝘀𝘁á 𝘂𝘀𝗮𝗻𝗱𝗼 𝗦𝗦𝗛?&lt;/span&gt;
ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github.com-fintech
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;𝗗𝗲𝗯𝗲𝗿í𝗮𝘀 𝘃𝗲𝗿: "𝗛𝗶 @𝘂𝘀𝘂𝗮𝗿𝗶𝗼-𝗳𝗶𝗻𝘁𝗲𝗰𝗵! 𝗬𝗼𝘂'𝘃𝗲 𝘀𝘂𝗰𝗰𝗲𝘀𝘀𝗳𝘂𝗹𝗹𝘆 𝗮𝘂𝘁𝗵𝗲𝗻𝘁𝗶𝗰𝗮𝘁𝗲𝗱..."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ¿𝗤𝘂é 𝘂𝘀𝘂𝗮𝗿𝗶𝗼 𝘁𝗶𝗲𝗻𝗲 𝗚𝗶𝘁 𝗰𝗼𝗻𝗳𝗶𝗴𝘂𝗿𝗮𝗱𝗼?&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; .git/config | &lt;span class="nb"&gt;grep &lt;/span&gt;email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 𝗩𝗲𝗿 𝘁𝗼𝗱𝗮𝘀 𝗹𝗮𝘀 𝗸𝗲𝘆𝘀 𝗰𝗮𝗿𝗴𝗮𝗱𝗮𝘀&lt;/span&gt;
ssh-add &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 𝗧𝗲𝘀𝘁 𝗱𝗲 𝗰𝗼𝗻𝗲𝘅𝗶ó𝗻 𝘃𝗲𝗿𝗯𝗼𝘀𝗲 (𝗰𝘂𝗮𝗻𝗱𝗼 𝘁𝗼𝗱𝗼 𝗳𝗮𝗹𝗹𝗮)&lt;/span&gt;
ssh &lt;span class="nt"&gt;-vT&lt;/span&gt; git@github.com-fintech
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 🔥 LIMPIAR TODO Y EMPEZAR DE CERO (cuando hay caos)&lt;/span&gt;
ssh-add &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;span class="c"&gt;# Esto elimina TODAS las llaves del agente SSH&lt;/span&gt;
&lt;span class="c"&gt;# Útil cuando tienes conflictos de keys o credenciales mezcladas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Errores Comunes y Soluciones:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Causa&lt;/th&gt;
&lt;th&gt;Solución Mágica&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Permission denied&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Key incorrecta&lt;/td&gt;
&lt;td&gt;Verifica &lt;code&gt;~/.ssh/config&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Could not open connection&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Alias mal escrito&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;github.com-empresa&lt;/code&gt; vs &lt;code&gt;github.com_empresa&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;User email incorrecto&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Git local mal config&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git config user.email&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🧭 ¿Y si trabajamos juntos?
&lt;/h2&gt;

&lt;p&gt;Este proyecto es una base.En &lt;strong&gt;CrossCloudX&lt;/strong&gt;, diseñamos pipelines a la medida para empresas financieras, consultoras o startups con visión.&lt;br&gt;
¿Te interesa un piloto en tu empresa?&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>github</category>
      <category>devops</category>
      <category>crosscloudx</category>
    </item>
    <item>
      <title>GitHub Actions + Security Scanning: Cómo Integrar Trivy y Checkov en tu Pipeline</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Mon, 19 Jan 2026 02:06:04 +0000</pubDate>
      <link>https://forem.com/francotel/github-actions-security-scanning-como-integrar-trivy-y-checkov-en-tu-pipeline-3klg</link>
      <guid>https://forem.com/francotel/github-actions-security-scanning-como-integrar-trivy-y-checkov-en-tu-pipeline-3klg</guid>
      <description>&lt;h2&gt;
  
  
  🚨 La Pesadilla que Todos los DevOps Tememos
&lt;/h2&gt;

&lt;p&gt;Era un martes cualquiera cuando recibí la alerta: &lt;strong&gt;"Vulnerabilidad CRÍTICA detectada en producción"&lt;/strong&gt;. Nuestra aplicación, que servía a miles de usuarios, tenía una vulnerabilidad de día cero que alguien había logrado explotar.&lt;/p&gt;

&lt;p&gt;¿El culpable? Una imagen Docker que habíamos desplegado la semana anterior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La peor parte&lt;/strong&gt;: ¡La vulnerabilidad ya existía cuando publicamos la imagen! Había pasado por nuestro pipeline CI/CD sin que nadie la notara.&lt;/p&gt;

&lt;p&gt;En ese momento entendí algo crucial: &lt;strong&gt;si tu pipeline no valida seguridad, estás desplegando ciegamente&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛡️ La Solución: Integrar Security Scanning en GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Después de esa experiencia, me propuse crear un pipeline que &lt;strong&gt;nunca más&lt;/strong&gt; permitiera que vulnerabilidades llegaran a producción. Así nació este proyecto que hoy comparto contigo.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔍 El Problema que Resolvemos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Así era nuestro workflow ANTES:&lt;/span&gt;
- name: Build Docker Image
  run: docker build &lt;span class="nt"&gt;-t&lt;/span&gt; mi-app &lt;span class="nb"&gt;.&lt;/span&gt;


- name: Push to Registry  
  run: docker push mi-app:latest

&lt;span class="c"&gt;# ¡Sin validaciones de seguridad!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resultado&lt;/strong&gt;: Vulnerabilidades, secretos expuestos, configuraciones inseguras... todo llegando a producción.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 La Arquitectura de Nuestro Pipeline Seguro
&lt;/h2&gt;

&lt;p&gt;Nuestro nuevo pipeline tiene 4 fases críticas:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;🐳 Construcción con Etiquetas Inteligentes&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Tags únicos por commit + ambiente&lt;/span&gt;
IMAGE_TAG_SHA: "sha-${GITHUB_SHA::7}"
IMAGE_TAG_ENV: "${{ inputs.target_env }}-latest"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;🔍 Escaneo de Vulnerabilidades con Trivy
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security Scan con Trivy&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;docker run --rm \&lt;/span&gt;
      &lt;span class="s"&gt;-v $(pwd):/src \&lt;/span&gt;
      &lt;span class="s"&gt;aquasec/trivy:latest \&lt;/span&gt;
      &lt;span class="s"&gt;image --severity CRITICAL,HIGH \&lt;/span&gt;
      &lt;span class="s"&gt;mi-imagen:${TAG}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trivy nos ayuda a encontrar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Vulnerabilidades en paquetes del sistema&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependencias con CVEs conocidos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secretos expuestos accidentalmente&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configuraciones inseguras&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;🏗️ Validación de Dockerfile con Checkov&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IaC Security con Checkov&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;docker run --rm \&lt;/span&gt;
      &lt;span class="s"&gt;bridgecrew/checkov \&lt;/span&gt;
      &lt;span class="s"&gt;--file Dockerfile \&lt;/span&gt;
      &lt;span class="s"&gt;--framework dockerfile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checkov revisa que nuestro Dockerfile siga mejores prácticas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;¿Usuario root? ❌&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;¿Paquetes sin actualizar? ❌&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;¿Secretos hardcodeados? ❌&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;🚫 Bloqueo Automático en Fallos&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;La magia está aquí: &lt;strong&gt;si hay vulnerabilidades CRÍTICAS o ALTAS, el pipeline SE DETIENE&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;if [ "$VULNERABILIDADES" -gt 0 ]; then&lt;/span&gt;
  &lt;span class="s"&gt;echo "❌ WORKFLOW BLOQUEADO"&lt;/span&gt;
  &lt;span class="s"&gt;echo "Hay $VULNERABILIDADES problemas de seguridad"&lt;/span&gt;
  &lt;span class="s"&gt;exit &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📊 Dashboard de Seguridad en Tiempo Real
&lt;/h3&gt;

&lt;p&gt;Lo mejor de todo: &lt;strong&gt;todo aparece automáticamente en GitHub Actions Summary&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;🐳 Reporte de Escaneo - Trivy
══════════════════════════════

📊 Resumen General
──────────────────
| Tipo              | Severidad  | Cantidad |
|-------------------|------------|----------|
| Vulnerabilidades  | 🔴 CRÍTICA | 2        |
| Vulnerabilidades  | 🟠 ALTA    | 9        |
| Total             |            | 11       |

🏗️ Checkov Security Scan  
══════════════════════════

✅ Todos los checks pasaron &lt;span class="o"&gt;(&lt;/span&gt;22 passed, 0 failed&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🎯 El Resultado: Confianza Automatizada
&lt;/h3&gt;




&lt;p&gt;&lt;strong&gt;Antes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"Ojalá no haya vulnerabilidades"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auditorías manuales cada 3 meses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incidentes de seguridad recurrentes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Después&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Cada commit&lt;/strong&gt; validado automáticamente&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Cada imagen&lt;/strong&gt; escaneada antes de publicar&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Cada despliegue&lt;/strong&gt; con reporte de seguridad&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Cero&lt;/strong&gt; vulnerabilidades en producción desde la implementación&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlxdftv5dtqruyupzv4n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlxdftv5dtqruyupzv4n.png" alt="trivy-1" width="514" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhapixrmd2s0zvhd0faq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhapixrmd2s0zvhd0faq.png" alt="trivy-2" width="542" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05067r6jveg5eh9yvwvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05067r6jveg5eh9yvwvp.png" alt="checkov-1" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💡 Lecciones Aprendidas
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Seguridad ≠ Lentitud&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Muchos piensan que agregar security scanning hará lento el pipeline. ¡Falso! Nuestros escaneos agregan solo 2-3 minutos.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Fail Fast es Mejor que Fail in Production&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Preferimos que falle el pipeline (y notifique al desarrollador) a que falle en producción (y afecte a usuarios).&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Los Reportes Son Tu Mejor Aliado&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Un reporte claro y automático hace que los equipos &lt;strong&gt;entiendan y arreglen&lt;/strong&gt; los problemas, no solo los "parcheen".&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 Implementa en 3 Pasos Sencillos
&lt;/h3&gt;

&lt;p&gt;==================================&lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 1: Clona y explora
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/francotel/docker-image-security-scan  
&lt;span class="nb"&gt;cd &lt;/span&gt;docker-image-security-scan   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 2: Examina el workflow
&lt;/h3&gt;

&lt;p&gt;Revisa .github/workflows/publish-nginx-image.yml - ¡todo está listo para usar!&lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 3: Adapta a tu caso
&lt;/h3&gt;

&lt;p&gt;Modifica nombres de imágenes, registros y políticas según tu stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  📈 Impacto Inmediato
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Detección&lt;/strong&gt;: De trimestral a &lt;strong&gt;en cada commit&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cobertura&lt;/strong&gt;: De muestras a &lt;strong&gt;100% de imágenes&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Confianza&lt;/strong&gt;: De "espero" a &lt;strong&gt;"sé que está validado"&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤝 ¿Cómo Contribuir?
&lt;/h2&gt;

&lt;p&gt;El proyecto está activo en &lt;a href="https://github.com/francotel/docker-image-security-scan" rel="noopener noreferrer"&gt;&lt;strong&gt;github.com/francotel/docker-image-security-scan&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Ideas para mejorar?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Notificaciones en Slack/Teams&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dashboard histórico&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Escaneo automático de imágenes base&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Policy as Code personalizado&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎯 ¡Hazlo Hoy!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ventajas clave:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Gratuito&lt;/strong&gt; (open source)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Simple&lt;/strong&gt; (un archivo YAML)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Efectivo&lt;/strong&gt; (bloquea problemas reales)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Acción inmediata:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;⭐ &lt;strong&gt;Dale estrella&lt;/strong&gt; al repo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🐑 &lt;strong&gt;Haz fork y adapta&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;💬 &lt;strong&gt;Comenta en issues&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;¿Listo para seguridad automatizada?&lt;/strong&gt;👉 &lt;a href="https://github.com/francotel/docker-image-security-scan" rel="noopener noreferrer"&gt;&lt;strong&gt;github.com/francotel/docker-image-security-scan&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#DevSecOps #GitHubActions #DockerSecurity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;¡No te lo pierdas! Sígueme en LinkedIn para estar al tanto de todas las actualizaciones y futuros artículos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ☕ Apóyame con un café
&lt;/h3&gt;

&lt;p&gt;Si este contenido te ha sido útil y quieres apoyarme para seguir creando más, considera invitarme un café. ¡Tu apoyo hace la diferencia! 🥰&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;¡Gracias por leer y hasta la próxima! 👋&lt;/p&gt;

</description>
      <category>docker</category>
      <category>crosscloudx</category>
      <category>devops</category>
      <category>github</category>
    </item>
    <item>
      <title>🚀 ¡Despídete del Caos de Configs! Mi Viaje con Azure App Configuration: Escalabilidad, Seguridad y 0 Downtimes en Microservicios</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Thu, 13 Nov 2025 03:04:45 +0000</pubDate>
      <link>https://forem.com/francotel/despidete-del-caos-de-configs-mi-viaje-con-azure-app-configuration-escalabilidad-seguridad-y-52g7</link>
      <guid>https://forem.com/francotel/despidete-del-caos-de-configs-mi-viaje-con-azure-app-configuration-escalabilidad-seguridad-y-52g7</guid>
      <description>&lt;p&gt;💭 &lt;strong&gt;Imagina esto:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Eres un desarrollador apasionado (como yo 😅) que lleva semanas lidiando con configs dispersos entre YAMLs, repositorios Git y variables de entorno olvidadas.&lt;br&gt;&lt;br&gt;
Tus microservicios en &lt;strong&gt;Node.js&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt; y &lt;strong&gt;Go&lt;/strong&gt; crecen rápido, pero cada cambio —por mínimo que sea, como actualizar un &lt;code&gt;db.host&lt;/code&gt;— termina en &lt;strong&gt;reinicios manuales&lt;/strong&gt;, &lt;strong&gt;merge conflicts&lt;/strong&gt; y &lt;strong&gt;noches sin dormir&lt;/strong&gt; tratando de entender por qué algo rompió en producción. 😵‍💫  &lt;/p&gt;

&lt;p&gt;Un viernes (sí, &lt;em&gt;otro viernes de deploys peligrosos&lt;/em&gt;), decidí que ya era suficiente. Ese día conocí a &lt;strong&gt;Azure App Configuration&lt;/strong&gt;, y fue como pasar del caos al control total.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbGhlNjdwMXhxd3dqYWN2ZnZsYWVjNDd1N3pqd2NwbDdiYmNseG9iZyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2Fy9DIEU4LhCizDUzE5o%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbGhlNjdwMXhxd3dqYWN2ZnZsYWVjNDd1N3pqd2NwbDdiYmNseG9iZyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2Fy9DIEU4LhCizDUzE5o%2Fgiphy.gif" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  ☁️ El Giro de la Historia: Cómo App Configuration Salvó Mi Proyecto
&lt;/h2&gt;

&lt;p&gt;Primero, abrí el Portal de Azure y creé mi &lt;strong&gt;App Configuration Store&lt;/strong&gt; — literalmente un par de clics.&lt;br&gt;&lt;br&gt;
De pronto tenía un &lt;strong&gt;repositorio centralizado&lt;/strong&gt; de configuraciones donde podía definir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔑 Key-Value pairs (&lt;code&gt;app.name=MiServicio&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;🚦 Feature flags para rollouts dinámicos&lt;/li&gt;
&lt;li&gt;🔐 Referencias a secretos en &lt;strong&gt;Key Vault&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mi código cambió de esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// El viejo infierno 😅&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbHost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_HOST&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;a esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// El nuevo orden ⚡️&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbHost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getConfigurationSetting&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db.host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y sin reiniciar nada.&lt;br&gt;
Los SDKs de Azure cachean los valores localmente, así que ni latencia ni downtime.&lt;/p&gt;

&lt;p&gt;Cada microservicio —desde mi clúster de Kubernetes hasta mis pipelines— empezó a hablar el mismo idioma de configuración.&lt;/p&gt;
&lt;h2&gt;
  
  
  💎 Ventajas que Brillaron en Mis Entrevistas
&lt;/h2&gt;

&lt;p&gt;Cuando comencé a implementar &lt;strong&gt;Azure App Configuration&lt;/strong&gt;, no solo resolví problemas técnicos: también logré destacar en entrevistas de arquitectura y DevOps. Cada punto fuerte del servicio se transformó en una historia concreta que demostraba control, escalabilidad y visión de futuro.  &lt;/p&gt;


&lt;h3&gt;
  
  
  🌍 Escalabilidad sin límites
&lt;/h3&gt;

&lt;p&gt;Azure maneja miles de requests con un &lt;strong&gt;99.9% de disponibilidad garantizada&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
En mi demo, App Configuration procesó más de &lt;strong&gt;10,000 lecturas diarias&lt;/strong&gt; sin una sola caída — ideal para entornos híbridos con microservicios distribuidos en &lt;strong&gt;Kubernetes&lt;/strong&gt; o &lt;strong&gt;AKS&lt;/strong&gt;.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;em&gt;Ejemplo que compartí en una entrevista:&lt;/em&gt; “Gracias al cacheo local del SDK, mis servicios siguieron operando incluso durante una breve desconexión del Portal de Azure.”  &lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  🔐 Seguridad empresarial
&lt;/h3&gt;

&lt;p&gt;La integración con &lt;strong&gt;Azure Key Vault&lt;/strong&gt; fue un cambio de juego.&lt;br&gt;&lt;br&gt;
En lugar de almacenar contraseñas o tokens directamente, App Configuration &lt;strong&gt;solo guarda la referencia segura&lt;/strong&gt; del secreto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://myvault.vault.azure.net/secrets/db-password"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🧩 Demo en Acción: App Configuration + Node.js + Terraform
&lt;/h2&gt;

&lt;p&gt;Para llevar esta historia más allá del papel, preparé una &lt;strong&gt;demo funcional&lt;/strong&gt; que combina &lt;strong&gt;Azure App Configuration&lt;/strong&gt;, &lt;strong&gt;Terraform&lt;/strong&gt; y &lt;strong&gt;Node.js&lt;/strong&gt; en un entorno totalmente automatizado.  &lt;/p&gt;

&lt;p&gt;El servidor &lt;strong&gt;Node.js&lt;/strong&gt; renderiza en tiempo real los valores definidos en &lt;strong&gt;App Configuration&lt;/strong&gt; — título, color de fondo y tamaño de fuente — &lt;strong&gt;sin necesidad de reiniciar el contenedor&lt;/strong&gt;.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 &lt;em&gt;Cada cambio que hagas desde el Portal de Azure se refleja automáticamente en la UI del servidor.&lt;/em&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;📦 Puedes revisar el código completo y probarlo tú mismo en mi repositorio:&lt;br&gt;&lt;br&gt;
👉 &lt;a href="https://github.com/francotel/azure-app-config-terraform-demo" rel="noopener noreferrer"&gt;https://github.com/francotel/azure-app-config-terraform-demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8ptnusq71bg8ytkyx5g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8ptnusq71bg8ytkyx5g.gif" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧭 ¿Y si trabajamos juntos?
&lt;/h2&gt;

&lt;p&gt;Este proyecto es una base.En &lt;strong&gt;CrossCloudX&lt;/strong&gt;, diseñamos pipelines a la medida para empresas financieras, consultoras o startups con visión.&lt;br&gt;
¿Te interesa un piloto en tu empresa?&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>devops</category>
      <category>azure</category>
      <category>crosscloudx</category>
      <category>terraform</category>
    </item>
    <item>
      <title>🛡️ Elimina secretos, escanea dependencias y duerme tranquilo: Así funciona un pipeline moderno DevSecOps</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Thu, 24 Jul 2025 22:56:00 +0000</pubDate>
      <link>https://forem.com/francotel/elimina-secretos-escanea-dependencias-y-duerme-tranquilo-asi-funciona-un-pipeline-moderno-27d3</link>
      <guid>https://forem.com/francotel/elimina-secretos-escanea-dependencias-y-duerme-tranquilo-asi-funciona-un-pipeline-moderno-27d3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🔍 “¿Y si hoy tu build revelara una clave secreta en producción?”&lt;/p&gt;

&lt;p&gt;💣 “¿Y si una librería obsoleta estuviera exponiendo tu app bancaria sin que lo sepas?”&lt;/p&gt;

&lt;p&gt;Esta es la historia real de cómo un pipeline bien diseñado salvó a un equipo de infraestructura de un incidente de seguridad mayor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ☁️ El dilema: Seguridad vs Velocidad
&lt;/h2&gt;

&lt;p&gt;Muchos equipos de desarrollo y DevOps se enfrentan al mismo conflicto:&lt;strong&gt;“¿Cómo integramos seguridad sin frenar nuestros despliegues?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En consultorías, bancos y empresas tech, he visto pipelines que usan hojas de Excel para reportar vulnerabilidades. Sí, &lt;strong&gt;Excel&lt;/strong&gt; en pleno 2025. 🧟‍♂️&lt;/p&gt;

&lt;p&gt;La consecuencia:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Secretos hardcodeados en el código fuente 😱&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependencias con vulnerabilidades críticas 🐛&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mala visibilidad en auditorías 🔍&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 La solución: Un pipeline CI con visión DevSecOps
&lt;/h2&gt;

&lt;p&gt;He creado una PoC que &lt;strong&gt;automatiza seguridad desde el primer push&lt;/strong&gt;, sin sacrificar la velocidad.&lt;br&gt;
🔗 &lt;strong&gt;Repositorio público&lt;/strong&gt;: &lt;a href="https://github.com/francotel/gitsecops-cicd-poc" rel="noopener noreferrer"&gt;gitsecops-cicd-poc&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  👇 ¿Qué incluye esta primera fase CI?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmt2zoagwrar2bgrncjfx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmt2zoagwrar2bgrncjfx.gif" alt="ci-devsecops" width="1048" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Etapas del pipeline:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Etapa&lt;/th&gt;
&lt;th&gt;Herramienta&lt;/th&gt;
&lt;th&gt;Qué detecta 🕵️&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Checkout Code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GitHub Actions&lt;/td&gt;
&lt;td&gt;Descarga del código&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Cache Trivy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trivy&lt;/td&gt;
&lt;td&gt;Optimiza tiempos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Secrets Scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trivy&lt;/td&gt;
&lt;td&gt;🔐 Claves, tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Configs Scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trivy&lt;/td&gt;
&lt;td&gt;🛡️ Permisos inseguros&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Build Docker Image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Compilación controlada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Dependencies Scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trivy (SCA)&lt;/td&gt;
&lt;td&gt;📦 CVEs en libs y SO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Notify&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Slack Webhook&lt;/td&gt;
&lt;td&gt;📢 Alertas en tiempo real&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🧪 ¿Por qué Trivy?
&lt;/h2&gt;

&lt;p&gt;Trivy no solo escanea imágenes Docker.También detecta:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Secrets en el código fuente (AWS keys, tokens, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Errores de configuración en YAMLs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vulnerabilidades en dependencias (package.json, requirements.txt, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CVEs a nivel de sistema operativo (Alpine, Debian, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Todo esto en &lt;strong&gt;menos de 2 minutos&lt;/strong&gt; por pipeline.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🧠 Caso de uso empresarial
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;Contexto: Consultora de seguridad financiera&lt;/strong&gt;&lt;br&gt;
Una fintech tenía múltiples microservicios desplegados sin control de versiones ni escaneo de imágenes.&lt;br&gt;
Con este pipeline CI se logró:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Detectar más de &lt;strong&gt;30 secretos hardcodeados&lt;/strong&gt; antes del merge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visibilidad en Slack de cada build inseguro&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aprobación interna de seguridad sin llenar formularios&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Resultado: Cumplieron auditoría SOX en tiempo récord. 🎯&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80v9wu61dsi6jd3poxoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80v9wu61dsi6jd3poxoj.png" alt="github-summary" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlg5skt0l7skb8g5vq4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvlg5skt0l7skb8g5vq4s.png" alt="slack" width="631" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔜 ¿Y el CD?
&lt;/h2&gt;

&lt;p&gt;Este post cubre &lt;strong&gt;solo la etapa CI&lt;/strong&gt;.La segunda parte incluirá:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Despliegue en ambientes segregados (Dev, UAT, Prod)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validación post-deploy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Políticas de rollback&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Escaneo en tiempo de ejecución&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠️ ¿Cómo empezar?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Clona el repo 👉 git clone &lt;a href="https://github.com/francotel/gitsecops-cicd-poc" rel="noopener noreferrer"&gt;https://github.com/francotel/gitsecops-cicd-poc&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agrega tu workflow.yml desde la carpeta .github/workflows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Crea tu webhook de Slack para recibir alertas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎯 Ejecuta un push y deja que Trivy haga su magia&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🧠 Bonus: Hacks que usamos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🔄 Cacheo de Trivy para escanear más rápido&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🕵️‍♂️ Reglas personalizadas para detectar secretos locales&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔐 Uso de chmod 777 como &lt;em&gt;trampa&lt;/em&gt; para validación&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🤖 Notificación temprana al equipo antes del merge&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧯¿Por qué esto es mejor que Excel?
&lt;/h2&gt;

&lt;p&gt;ExcelDevSecOps PipelineManual, lento, reactivoAutomático, veloz, proactivoRequiere validación humanaIntegración directa al códigoDifícil de auditarLogs en tiempo realSilos entre equiposSeguridad como parte del DevOps&lt;/p&gt;

&lt;h2&gt;
  
  
  🧭 ¿Y si trabajamos juntos?
&lt;/h2&gt;

&lt;p&gt;Este proyecto es una base.En &lt;strong&gt;CrossCloudX&lt;/strong&gt;, diseñamos pipelines a la medida para empresas financieras, consultoras o startups con visión.&lt;br&gt;
¿Te interesa un piloto en tu empresa?&lt;br&gt;
📩 Escríbeme o abre un issue en el repo: &lt;a href="https://github.com/francotel/gitsecops-cicd-poc" rel="noopener noreferrer"&gt;gitsecops-cicd-poc&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 TL;DR
&lt;/h2&gt;

&lt;p&gt;✅ Pipeline CI moderno con Trivy&lt;br&gt;
✅ Escaneo de secretos, dependencias y configuración&lt;br&gt;
✅ Notificación directa a Slack&lt;br&gt;
✅ Base sólida para DevSecOps real&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>devops</category>
      <category>trivy</category>
      <category>github</category>
      <category>crosscloudx</category>
    </item>
    <item>
      <title>Run IBM DataPower in Docker in 5 Minutes! 🚀 (No IBM Cloud Needed!)</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Tue, 03 Jun 2025 03:09:24 +0000</pubDate>
      <link>https://forem.com/francotel/run-ibm-datapower-in-docker-in-5-minutes-no-ibm-cloud-needed-3lo7</link>
      <guid>https://forem.com/francotel/run-ibm-datapower-in-docker-in-5-minutes-no-ibm-cloud-needed-3lo7</guid>
      <description>&lt;p&gt;&lt;em&gt;"IBM DataPower is a powerful API gateway, but it's usually locked behind complex setups. Let’s run it locally with Docker—no licenses or cloud accounts required!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuoc9vi6z7rb3l5w9w0ms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuoc9vi6z7rb3l5w9w0ms.png" alt="datapower" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 What You’ll Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; installed (👉 &lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;Install guide&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 minutes&lt;/strong&gt; of time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terminal&lt;/strong&gt; (Bash or ZSH)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 Before We Start: About Skopeo
&lt;/h2&gt;

&lt;p&gt;Need to check container versions &lt;em&gt;before&lt;/em&gt; downloading? &lt;strong&gt;Skopeo&lt;/strong&gt; is your friend! This handy tool lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔎 &lt;strong&gt;Inspect images&lt;/strong&gt; without pulling them&lt;/li&gt;
&lt;li&gt;🏷️ &lt;strong&gt;List available versions&lt;/strong&gt; (tags)&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Copy images&lt;/strong&gt; between registries
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skopeo list-tags docker://icr.io/cpopen/datapower/datapower-limited
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65eczcjaa6k0i8h4hmt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65eczcjaa6k0i8h4hmt1.png" alt="skopeo-tags" width="600" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📂 Step 1: Prep Your Workspace
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;datapower &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;datapower 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using version &lt;code&gt;2018.4.1.9&lt;/code&gt;&lt;/strong&gt; (stable and widely compatible):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Pull the specific DataPower version&lt;/span&gt;
docker pull icr.io/cpopen/datapower/datapower-limited:2018.4.1.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Launch the container with persistent configs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;/config:/drouter/config &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;/local:/drouter/local &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DATAPOWER_ACCEPT_LICENSE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DATAPOWER_INTERACTIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 9090:9090 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 9022:22 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8000-8010:8000-8010 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; idg &lt;span class="se"&gt;\&lt;/span&gt;
  icr.io/cpopen/datapower/datapower-limited:2018.4.1.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fduk767izw14qpim6sjcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fduk767izw14qpim6sjcd.png" alt="docker-run" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 Key Notes (Best Practices!)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🚪 &lt;strong&gt;Ports Management&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-port assignment&lt;/strong&gt;: For multi-container setups, use &lt;code&gt;-p 8000&lt;/code&gt; (let Docker choose host port)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port conflicts?&lt;/strong&gt; Remap the WebGUI (e.g., &lt;code&gt;-p 9191:9090&lt;/code&gt; → access via &lt;code&gt;http://localhost:9191&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📂 &lt;strong&gt;Folder Structure&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;datapower/
├── config/ &lt;span class="c"&gt;# Stores all configurations (edit directly!)&lt;/span&gt;
└── &lt;span class="nb"&gt;local&lt;/span&gt;/ &lt;span class="c"&gt;# For certificates, scripts (XSLT/JS), and keys&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔐 &lt;strong&gt;Security Must-Dos&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First step&lt;/strong&gt;: Change default credentials (&lt;code&gt;admin/admin&lt;/code&gt;)!
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production tip&lt;/strong&gt;: Disable &lt;code&gt;DATAPOWER_INTERACTIVE&lt;/code&gt; to avoid log clutter
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  🌐 Step 2: Enable the Web GUI
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In the running container's CLI&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   configure&lt;span class="p"&gt;;&lt;/span&gt; web-mgmt 0 9090&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c"&gt;# Activates WebGUI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7uzje8pqjw36ksrbyi4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7uzje8pqjw36ksrbyi4.png" alt="datapower-access" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access it&lt;/strong&gt;:&lt;br&gt;
URL: &lt;a href="https://localhost:9090" rel="noopener noreferrer"&gt;https://localhost:9090&lt;/a&gt;&lt;br&gt;
Credentials: admin / admin (change this!)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomlrzrwv39k01th917gq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomlrzrwv39k01th917gq.png" alt="datapower-gui-1" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl79bi9pqez36y94mnq54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl79bi9pqez36y94mnq54.png" alt="datapower-gui-2" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cleanup&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop idg &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker &lt;span class="nb"&gt;rm &lt;/span&gt;idg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🏁 Conclusion
&lt;/h2&gt;

&lt;p&gt;You've now got &lt;strong&gt;IBM DataPower&lt;/strong&gt; running in Docker in just minutes! Key takeaways:&lt;/p&gt;

&lt;p&gt;✓ &lt;strong&gt;Local testing&lt;/strong&gt; without expensive hardware&lt;br&gt;&lt;br&gt;
✓ &lt;strong&gt;Persistent configs&lt;/strong&gt; via Docker volumes&lt;br&gt;&lt;br&gt;
✓ &lt;strong&gt;Full access&lt;/strong&gt; to WebGUI and CLI  &lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>ibm</category>
      <category>datapower</category>
      <category>crosscloudx</category>
      <category>docker</category>
    </item>
    <item>
      <title>Kubernetes 1.33: Change Pod Size Without Restart! (No More Problems!)</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Fri, 30 May 2025 02:23:57 +0000</pubDate>
      <link>https://forem.com/francotel/kubernetes-133-change-pod-size-without-restart-no-more-problems-31pl</link>
      <guid>https://forem.com/francotel/kubernetes-133-change-pod-size-without-restart-no-more-problems-31pl</guid>
      <description>&lt;h3&gt;
  
  
  😅 The Problem Every DevOps Knows
&lt;/h3&gt;

&lt;p&gt;Imagine this: It's midnight, your app has too many users, and your Pods need more CPU and memory. But in Kubernetes, changing resources means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Delete and restart the Pods&lt;/strong&gt; (bye-bye, active connections!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait for a rolling update&lt;/strong&gt; (more waiting time)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hope there's no downtime&lt;/strong&gt; (but there's always some)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Until now, changing Pod resources &lt;strong&gt;required a restart&lt;/strong&gt;. But with &lt;strong&gt;Kubernetes 1.33, this is no longer true!&lt;/strong&gt; 🎉&lt;/p&gt;




&lt;h3&gt;
  
  
  🚀 What's New? Pods That Grow Without Restarting!
&lt;/h3&gt;

&lt;p&gt;Now you can:&lt;br&gt;
✅ &lt;strong&gt;Increase/Decrease CPU and memory without restarting&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Works with StatefulSets&lt;/strong&gt; (great for databases!)&lt;br&gt;
✅ &lt;strong&gt;Choose if the Pod restarts on errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-life example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; An API gets 10x more traffic than usual&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Old way:&lt;/strong&gt; Rolling update → 30 seconds of downtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New way:&lt;/strong&gt; &lt;code&gt;kubectl patch&lt;/code&gt; → &lt;strong&gt;0 downtime&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 How to Use It? (Easy Code Example 🛠️)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Create a Pod with resize policy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scalable-app&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1Gi"&lt;/span&gt;
      &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2Gi"&lt;/span&gt;
    &lt;span class="na"&gt;resizePolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# The magic is here!&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;resourceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cpu&lt;/span&gt;
      &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NotRequired&lt;/span&gt;  &lt;span class="c1"&gt;# No restart if it fails&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;resourceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;memory&lt;/span&gt;
      &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NotRequired&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Change resources while running
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl patch pod scalable-app &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{
  "spec": {
    "containers": [{
      "name": "web",
      "resources": {
        "requests": {"cpu": "2", "memory": "2Gi"},
        "limits": {"cpu": "3", "memory": "3Gi"}
      }
    }]
  }
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Done! The Pod keeps running with more resources.
&lt;/h4&gt;

&lt;h3&gt;
  
  
  🏢 Why Is This Good for Companies?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;🔄 Less downtime&lt;/strong&gt; → Better for important apps
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;💰 Save cloud costs&lt;/strong&gt; → Reduce resources when not needed
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📈 Handle traffic spikes fast&lt;/strong&gt; → No waiting for deployments
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🗃️ Better for databases&lt;/strong&gt; → No restarts to change memory
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Any Problems?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not all runtimes support it yet&lt;/strong&gt; (check your CRI)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need to configure it&lt;/strong&gt; (add &lt;code&gt;resizePolicy&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New feature = possible bugs&lt;/strong&gt; (test first in staging)
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔚 Conclusion: A Big Step for Kubernetes
&lt;/h3&gt;

&lt;p&gt;Now you can &lt;strong&gt;change Pod resources without restarting&lt;/strong&gt;. No more choosing between "low resources" or "risky restarts".  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will you try it? Tell me in the comments!&lt;/strong&gt; 👇  &lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Did you like this?&lt;/strong&gt; Share and follow for more Kubernetes/DevOps posts. 🚀 &lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>crosscloudx</category>
    </item>
    <item>
      <title>Misconfigured S3 Buckets: Detect and Remediate with AWS Config + Lambda</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Wed, 07 May 2025 17:55:24 +0000</pubDate>
      <link>https://forem.com/francotel/misconfigured-s3-buckets-detect-and-remediate-with-aws-config-lambda-11p</link>
      <guid>https://forem.com/francotel/misconfigured-s3-buckets-detect-and-remediate-with-aws-config-lambda-11p</guid>
      <description>&lt;h2&gt;
  
  
  🚨 1. The Hidden Danger: S3 Buckets Left Public
&lt;/h2&gt;

&lt;p&gt;Many developers create S3 buckets using the default console settings, CLI scripts, or even automation templates (like CloudFormation or Terraform) — &lt;strong&gt;without fully reviewing access policies.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🎯 &lt;strong&gt;What could go wrong?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;public-read&lt;/code&gt; or &lt;code&gt;public-write&lt;/code&gt; is enabled by mistake&lt;/li&gt;
&lt;li&gt;Bucket policies allow &lt;code&gt;Principal: "*"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Static websites are deployed with no access restrictions&lt;/li&gt;
&lt;li&gt;Files contain sensitive data: &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;backup.zip&lt;/code&gt;, &lt;code&gt;user-data.csv&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Case Study&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A dev team created a bucket to share app logs for debugging. The bucket had public access, and after 3 weeks it was indexed by a search engine. It contained logs with API keys and customer email addresses.&lt;br&gt;&lt;br&gt;
💸 This resulted in an internal audit and months of cleanup work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7zpbcrwkmwhqr2arbya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7zpbcrwkmwhqr2arbya.png" alt="s3-mis" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔎 2. What Causes These Misconfigurations?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rushed deployment with &lt;code&gt;aws s3api create-bucket&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CI/CD pipelines that skip security checks&lt;/li&gt;
&lt;li&gt;Inexperienced teams who don't understand IAM or bucket policy syntax&lt;/li&gt;
&lt;li&gt;Copy-pasted infrastructure templates with bad defaults&lt;/li&gt;
&lt;li&gt;Developers assume "private unless shared" — but &lt;strong&gt;S3 can default to public&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ 3. Consequences of Misconfigured Buckets
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🕵️‍♂️ Data Exposure&lt;/td&gt;
&lt;td&gt;Customer data, code, secrets available online&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💰 Cost Spike&lt;/td&gt;
&lt;td&gt;Public write access can be exploited to store malware or pirated files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❌ Compliance Violation&lt;/td&gt;
&lt;td&gt;Breach of GDPR, HIPAA, SOC2 or ISO27001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📉 Reputational Damage&lt;/td&gt;
&lt;td&gt;Public trust loss, press coverage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🛠️ Incident Response&lt;/td&gt;
&lt;td&gt;Reactive patching, forensic work, legal reports&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ 4. How to Fix It Automatically
&lt;/h2&gt;

&lt;h3&gt;
  
  
  💡 Best combo: &lt;strong&gt;AWS Config + Lambda&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;🧭 &lt;strong&gt;AWS Config&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Monitors and evaluates your AWS resources against a list of compliance rules. For S3, it can detect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public read/write access&lt;/li&gt;
&lt;li&gt;Missing encryption&lt;/li&gt;
&lt;li&gt;Logging not enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚙️ &lt;strong&gt;AWS Lambda&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Executes custom code to fix non-compliant resources, instantly and automatically.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Together, they create a &lt;strong&gt;self-healing cloud security workflow&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🛡️ AWS Config Rules: Managed vs. Custom (S3 Security Demo)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;🔧 Managed Rules (AWS)&lt;/th&gt;
&lt;th&gt;⚡ Custom Rules (Your Code)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🚀 Setup Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Instant (~1 minute)&lt;/td&gt;
&lt;td&gt;⏳ 15-30 mins (coding required)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🔧 Maintenance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🤖 Fully automated by AWS&lt;/td&gt;
&lt;td&gt;👨💻 Your team maintains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;💡 Intelligence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;📜 Fixed logic (CIS benchmarks)&lt;/td&gt;
&lt;td&gt;🧠 Your custom business logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🔒 S3 Protection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🛡️ Basic security checks&lt;/td&gt;
&lt;td&gt;🛡️🛡️🛡️ Advanced protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;💸 Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;💰 Included in Config pricing&lt;/td&gt;
&lt;td&gt;💰💰 + Lambda costs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🛠️ Demo Ready?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Too generic&lt;/td&gt;
&lt;td&gt;✅ Perfect for custom demos!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I'm Choosing Custom Rules for Precision Targeting 🎯  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔐 Auto-Securing S3 Buckets with AWS Config &amp;amp; Lambda
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;🚀 Full Architecture &amp;amp; Deployment Code on GitHub&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffygf0pyt984y8w6dmjnj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffygf0pyt984y8w6dmjnj.gif" alt="archi" width="914" height="644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This automated solution protects your S3 buckets by:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Detecting risks&lt;/strong&gt; → Unencrypted buckets/public access
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-fixing issues&lt;/strong&gt; → Enforces KMS encryption &amp;amp; security settings
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintaining compliance&lt;/strong&gt; → Continuous AWS Config monitoring
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✨ &lt;strong&gt;Key Features&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform-powered&lt;/strong&gt; infrastructure
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python Lambda&lt;/strong&gt; remediation logic
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-touch&lt;/strong&gt; security enforcement
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo mode&lt;/strong&gt; included for testing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📦 &lt;strong&gt;GitHub Repo Includes&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
✅ Complete Terraform deployment&lt;br&gt;&lt;br&gt;
✅ Lambda source code&lt;br&gt;&lt;br&gt;
✅ Architecture diagrams&lt;br&gt;&lt;br&gt;
✅ Step-by-step instructions  &lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://github.com/francotel/auto-fix-s3-buckets-with-terraform" rel="noopener noreferrer"&gt;Get the Code →&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔄 Before Fix&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🚨 Non-compliant bucket:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No encryption ❌
&lt;/li&gt;
&lt;li&gt;Public access allowed ❌
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚡ After Auto-Remediation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ Encryption enabled (KMS)&lt;br&gt;&lt;br&gt;
✅ Public access blocked&lt;br&gt;&lt;br&gt;
🕒 Compliance achieved in &amp;lt;1 minute  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8xjjaq7n4osg9wduanf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8xjjaq7n4osg9wduanf.png" alt="remediation1" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uiqniwn5yv7g6gxrsih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uiqniwn5yv7g6gxrsih.png" alt="remediation2" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>crosscloudx</category>
      <category>s3</category>
    </item>
    <item>
      <title>🛠️ Automate AMI Builds with Packer + EC2 Image Builder</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Tue, 15 Apr 2025 11:37:27 +0000</pubDate>
      <link>https://forem.com/francotel/automate-ami-builds-with-packer-ec2-image-builder-3p70</link>
      <guid>https://forem.com/francotel/automate-ami-builds-with-packer-ec2-image-builder-3p70</guid>
      <description>&lt;h3&gt;
  
  
  📦 DevOps Battle for Golden Images in AWS
&lt;/h3&gt;




&lt;h2&gt;
  
  
  🧭 1. Why Automate AMI Builds?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Golden AMIs&lt;/strong&gt; ensure that all your EC2 instances start with consistent, hardened, and pre-configured environments.&lt;/p&gt;

&lt;p&gt;❌ Manual builds = human errors, time waste, inconsistent images&lt;br&gt;&lt;br&gt;
✅ Automated builds = repeatable, secure, auditable&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚔️ 2. Packer vs EC2 Image Builder: The Showdown
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;🧰 Packer&lt;/th&gt;
&lt;th&gt;🖼️ EC2 Image Builder&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🔧 Configuration Language&lt;/td&gt;
&lt;td&gt;JSON or HCL&lt;/td&gt;
&lt;td&gt;YAML or Console&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔄 Integration with CI/CD&lt;/td&gt;
&lt;td&gt;✅ Very flexible&lt;/td&gt;
&lt;td&gt;⚠️ Limited (manual triggers, EventBridge workaround)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🛡️ Security Controls&lt;/td&gt;
&lt;td&gt;✅ Custom via hardening scripts&lt;/td&gt;
&lt;td&gt;✅ SSM + IAM roles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📦 Output Formats&lt;/td&gt;
&lt;td&gt;AMIs, Docker, Vagrant, etc.&lt;/td&gt;
&lt;td&gt;AMIs (only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;☁️ AWS Native&lt;/td&gt;
&lt;td&gt;❌ Third-party tool&lt;/td&gt;
&lt;td&gt;✅ Fully managed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📜 Logging &amp;amp; Visibility&lt;/td&gt;
&lt;td&gt;CLI or external&lt;/td&gt;
&lt;td&gt;✅ CloudWatch logs, detailed history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧪 Testing AMIs&lt;/td&gt;
&lt;td&gt;Manual or via external tools&lt;/td&gt;
&lt;td&gt;✅ Supports testing phases (e.g., InSpec)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💰 Cost&lt;/td&gt;
&lt;td&gt;Low (runs in your own infra)&lt;/td&gt;
&lt;td&gt;Low, but requires pipeline resources&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🏁 TL;DR:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Packer&lt;/strong&gt; when you need portability and full control.
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;EC2 Image Builder&lt;/strong&gt; when you prefer AWS-native, low-maintenance pipelines.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔧 3. Demo: Building a Hardened Ubuntu AMI in Both Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option A: Using Packer + HCL
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Define &lt;code&gt;ubuntu.pkr.hcl&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;packer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;amazon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.2.8"&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github.com/hashicorp/amazon"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"amazon-ebs"&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami_name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"learn-packer-linux-aws"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-west-2"&lt;/span&gt;
  &lt;span class="nx"&gt;source_ami_filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu/images/*ubuntu-jammy-22.04-amd64-server-*"&lt;/span&gt;
      &lt;span class="nx"&gt;root-device-type&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ebs"&lt;/span&gt;
      &lt;span class="nx"&gt;virtualization-type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hvm"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;most_recent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;owners&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"099720109477"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;ssh_username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;build&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"learn-packer"&lt;/span&gt;
  &lt;span class="nx"&gt;sources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"source.amazon-ebs.ubuntu"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;provisioner&lt;/span&gt; &lt;span class="s2"&gt;"shell"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"sudo apt-get update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"sudo apt-get install -y nginx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Build the image:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;packer init &lt;span class="nb"&gt;.&lt;/span&gt;
packer build ubuntu.pkr.hcl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxc7cnpjcqyi3httogn3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxc7cnpjcqyi3httogn3.png" alt="packer-build" width="755" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5j4k7fnc0eshf6tc1mi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5j4k7fnc0eshf6tc1mi.png" alt="ami-ec2" width="648" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Option B: Using EC2 Image Builder
&lt;/h3&gt;

&lt;p&gt;Create a Recipe&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Example component in YAML:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;install-nginx&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Nginx&lt;/span&gt;
&lt;span class="na"&gt;phases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apt update&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apt install -y nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a Pipeline with:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Source AMI: Ubuntu 22.04&lt;/li&gt;
&lt;li&gt;Build Component: install-nginx&lt;/li&gt;
&lt;li&gt;Test Component (optional): e.g., check Nginx service&lt;/li&gt;
&lt;li&gt;Output: AMI in target region&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trigger manually or via EventBridge for automation (e.g., weekly builds)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5na0iuwkhy1n8mxm7qdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5na0iuwkhy1n8mxm7qdv.png" alt="ec2-image-builder" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 5. Conclusions &amp;amp; Recommendations
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🧰 Use &lt;strong&gt;Packer&lt;/strong&gt; if:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want cross-cloud image creation
&lt;/li&gt;
&lt;li&gt;You need integration with existing pipelines
&lt;/li&gt;
&lt;li&gt;You're comfortable managing infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🖼️ Use &lt;strong&gt;EC2 Image Builder&lt;/strong&gt; if:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're all-in on AWS
&lt;/li&gt;
&lt;li&gt;You want minimal setup with native controls
&lt;/li&gt;
&lt;li&gt;You want to integrate with AWS Config, IAM, and SSM easily&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>terraform</category>
      <category>crosscloudx</category>
    </item>
    <item>
      <title>Friday Deployments: A Horror Story 💀</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Fri, 21 Mar 2025 15:11:06 +0000</pubDate>
      <link>https://forem.com/francotel/friday-deployments-a-horror-story-4m12</link>
      <guid>https://forem.com/francotel/friday-deployments-a-horror-story-4m12</guid>
      <description>&lt;p&gt;It was &lt;strong&gt;4:55 PM on a Friday&lt;/strong&gt; at &lt;strong&gt;SpookyCloud Inc.&lt;/strong&gt;. &lt;strong&gt;Alice&lt;/strong&gt;, the lead developer, stretched her arms and smiled.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Just one last deployment before the weekend!"&lt;/em&gt; she said.  &lt;/p&gt;

&lt;p&gt;Bob, the DevOps engineer, looked up in horror. &lt;strong&gt;"Wait... you’re deploying on a Friday?"&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Relax, it’s just a small update. What could go wrong?"&lt;/em&gt; Alice laughed as she ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;☠️ Big mistake.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74777hafrtzb0xqfqfhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74777hafrtzb0xqfqfhw.png" alt="friday-deploy" width="600" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 &lt;strong&gt;The Chaos Begins&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At &lt;strong&gt;5:02 PM&lt;/strong&gt;, alerts flooded Slack:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🔥 500 Internal Server Error!&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;🔥 Database connection failed!&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;🔥 API Gateway timeout!&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The production site was &lt;strong&gt;down&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Bob frantically checked the logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;backend &lt;span class="nt"&gt;--tail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👀 &lt;strong&gt;ERROR: Missing database migration&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Alice gasped. &lt;em&gt;"Oh no... I forgot to apply the migration!"&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;Bob tried to roll back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl rollout undo deployment backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7hwte1qxfddpssz0dmj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7hwte1qxfddpssz0dmj.png" alt="callback" width="360" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;FAILED: Image not found&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;😨 &lt;em&gt;The rollback failed. They were trapped.&lt;/em&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  ⏳ &lt;strong&gt;The Longest Friday Night&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;By &lt;strong&gt;7:30 PM&lt;/strong&gt;, Bob and Alice were still debugging. Their Slack statuses changed to:  &lt;/p&gt;

&lt;p&gt;🛠️ &lt;strong&gt;“Fixing production 😭”&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;By &lt;strong&gt;9:45 PM&lt;/strong&gt;, the &lt;strong&gt;CTO&lt;/strong&gt; joined the call:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Why are we down? Who pushed to &lt;strong&gt;main&lt;/strong&gt; on a Friday?"&lt;/em&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alice turned pale. She felt a chill down her spine.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;"It was me... I thought it was safe..."&lt;/em&gt; she whispered.  &lt;/p&gt;

&lt;p&gt;The CTO sighed. &lt;em&gt;"Well, guess what? We’re all working late now."&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;By &lt;strong&gt;1:15 AM&lt;/strong&gt;, they finally fixed the issue. The site was back, but their weekend was ruined.  &lt;/p&gt;

&lt;h2&gt;
  
  
  📜 &lt;strong&gt;Lessons from the Nightmare&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;🕵️‍♂️ &lt;strong&gt;Never deploy on a Friday.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
📋 &lt;strong&gt;Test in staging first.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🔄 &lt;strong&gt;Always have a rollback plan.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🛑 &lt;strong&gt;Feature flags are your friend.&lt;/strong&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 &lt;strong&gt;Don't Let This Happen to You&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Do you &lt;strong&gt;really&lt;/strong&gt; want to risk your weekend? &lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🧟‍♂️ The Zombie Server That Wouldn’t Die 💀</title>
      <dc:creator>francotel</dc:creator>
      <pubDate>Wed, 12 Mar 2025 22:47:05 +0000</pubDate>
      <link>https://forem.com/francotel/the-zombie-server-that-wouldnt-die-45di</link>
      <guid>https://forem.com/francotel/the-zombie-server-that-wouldnt-die-45di</guid>
      <description>&lt;h2&gt;
  
  
  🕛 The Midnight Nightmare
&lt;/h2&gt;

&lt;p&gt;It was midnight at &lt;strong&gt;SpookyCloud Inc.&lt;/strong&gt;. The office was dark, and the only light came from &lt;strong&gt;Bob’s&lt;/strong&gt; laptop screen. He was tired, ready to go home when suddenly...  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🔔 Slack Alert: "EC2 instance terminated"&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"Finally," Bob sighed. That old server was deleted weeks ago.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd42xxep6z57ggwv1323v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd42xxep6z57ggwv1323v.png" alt="ec2-terminated" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But then... &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🔔 Slack Alert: "EC2 instance running"&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bob’s heart skipped a beat. "No... no way," he whispered.  &lt;/p&gt;

&lt;p&gt;He opened the AWS console — there it was, running again. He stopped it once more.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🔔 Slack Alert: "EC2 instance running"&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;😨 &lt;em&gt;The server was back... again.&lt;/em&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  💀 The Monster Grows Stronger
&lt;/h2&gt;

&lt;p&gt;Every time Bob stopped the server, it returned — stronger and angrier. The CPU usage climbed higher, draining resources like a hungry beast.  &lt;/p&gt;

&lt;p&gt;Bob checked the logs... &lt;strong&gt;nothing&lt;/strong&gt;. No deployments, no cron jobs. It was as if the server had a mind of its own.  &lt;/p&gt;

&lt;p&gt;He grabbed his keyboard and typed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-instances &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=instance-state-name,Values=running"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Reservations[*].Instances[*].[InstanceId,Tags]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📋 The result? No tags. No owner. No clues.
&lt;/h3&gt;

&lt;p&gt;"It's a ghost..." Bob muttered.&lt;/p&gt;

&lt;h2&gt;
  
  
  👁️ The Forgotten Curse
&lt;/h2&gt;

&lt;p&gt;Digging deeper, Bob discovered the truth — the server belonged to a forgotten Auto Scaling Group from an ex-employee. Each time the server died, the group brought it back to life... like a cursed tomb opening again and again.&lt;/p&gt;

&lt;p&gt;Bob’s fingers shook as he ran this final command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws autoscaling delete-auto-scaling-group &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--auto-scaling-group-name&lt;/span&gt; &lt;span class="s2"&gt;"zombie-asg"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--force-delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚰️ The server was gone. For real this time.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 The Moral of the Story
&lt;/h2&gt;

&lt;p&gt;Like any good fable, Bob learned important lessons that night:&lt;/p&gt;

&lt;p&gt;🧟‍♂️ Always tag your resources. A tagless server is a mystery waiting to haunt you.&lt;br&gt;
🧟‍♂️ Clean up old environments. Forgotten test systems may return from the grave.&lt;br&gt;
🧟‍♂️ Review your Auto Scaling Groups. Hidden triggers can summon the undead.&lt;br&gt;
🧟‍♂️ Automate cleanup tasks. Don’t leave ghost servers to haunt your bill.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 &lt;strong&gt;Let's Connect!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you find this repository useful and want to see more content like this, follow me on LinkedIn to stay updated on more projects and resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/franconavarro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n0txk0zfofh94t4rza7.png" alt="LinkedIn" width="300" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to support my work, you can buy me a coffee. Thank you for your support!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francotel" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyb3wzaeuqkdfb9utao8.png" alt="BuyMeACoffee" width="512" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>crosscloudx</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
