<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DevSecOps, AWS, Linux, Shell Scripting, Ansible, Terraform, Docker, Kubernetes, Jenkins, Github Actions, ArgoCD, Helm Charts, Observability and Monitoring, Prometheus, Grafana, Open Telementry & AIOPS]]></title><description><![CDATA[This publication will list the  issues and learnings that I encountered during my DevSecOps journey with the following topics: AWS, Linux, Shell Scripting, Ansi]]></description><link>https://mokri.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 31 Oct 2026 20:36:30 GMT</lastBuildDate><atom:link href="https://mokri.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[SSL/TLS certificate Life Cycle management automation through Terraform]]></title><description><![CDATA[🔐 SSL/TLS certificates expire. Outages caused by them don’t have to happen. Expired certificates are still behind some of the most avoidable outages. A…]]></description><link>https://mokri.hashnode.dev/ssl-tls-certificate-life-cycle-management-automation-through-terraform</link><guid isPermaLink="true">https://mokri.hashnode.dev/ssl-tls-certificate-life-cycle-management-automation-through-terraform</guid><dc:creator><![CDATA[Mohan Geddada]]></dc:creator><pubDate>Sun, 25 Oct 2026 15:40:10 GMT</pubDate><content:encoded><![CDATA[<p>🔐 SSL/TLS certificates expire. Outages caused by them don’t have to happen.</p>
<p>Expired certificates are still behind some of the most avoidable outages. A browser warning, failed API calls, broken mobile apps, all from one date someone forgot to track.</p>
<p>Renewal is also about to get more frequent. The CA/Browser Forum approved shorter maximum public TLS certificate lifetimes: 200 days since March 2026, 100 days in 2027, and 47 days by 2029. Manual renewal won’t keep up with that.</p>
<p>Here’s how I manage the full certificate lifecycle in AWS using ACM + Terraform. 👇</p>
<p>🔄 The lifecycle 1️⃣ Request → 2️⃣ Validate → 3️⃣ Deploy → 4️⃣ Monitor → 5️⃣ Renew → 6️⃣ Retire</p>
<p>1️⃣ Request the certificate (ACM)</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa2ed5136fd4c5ce1e071dc/480ccd5f-c508-4040-917f-fa89608d996e.png" alt="" style="display:block;margin:0 auto" />

<p><br />💡 Use DNS validation, not email. As long as the CNAME record stays in place, ACM renews the certificate automatically.</p>
<p>2️⃣ Automate DNS validation (Route 53)</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa2ed5136fd4c5ce1e071dc/b9163b77-2ba1-4d5e-9706-992a4dac0d4e.png" alt="" style="display:block;margin:0 auto" />

<p>3️⃣ Deploy to the load balancer</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa2ed5136fd4c5ce1e071dc/e91ed2b9-e3bd-4413-86c0-52d0355dc087.png" alt="" style="display:block;margin:0 auto" />

<p>💡 Reference the validation resource’s ARN, not the certificate’s. That way Terraform waits until the certificate is actually issued before attaching it.</p>
<p>💡 For CloudFront, the certificate must be in us-east-1. Use a provider alias:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa2ed5136fd4c5ce1e071dc/98135773-66f6-4d40-a90a-32b1d235cab3.png" alt="" style="display:block;margin:0 auto" />

<p>4️⃣ Monitor expiry. Trust auto-renewal, but verify it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa2ed5136fd4c5ce1e071dc/1bedfe67-cdcf-4475-8534-d6b71bc378f6.png" alt="" style="display:block;margin:0 auto" />

<p>💡 If one of these alerts fires on an ACM-managed DNS-validated certificate, auto-renewal has failed. The usual cause is a deleted validation CNAME.</p>
<hr />
<p>5️⃣ Renew &amp; 6️⃣ Retire ✅ ACM renews DNS-validated certificates on its own, with no redeploy needed for integrated services (ALB, CloudFront, API Gateway). ✅ create_before_destroy makes replacements (new SANs, key algorithm change) zero-downtime. ✅ Imported third-party certificates do not auto-renew, so automate re-import in your pipeline or move them to ACM. ✅ Run terraform destroy on retired environments so orphaned certificates and validation records don’t pile up.</p>
<p>#AWS #Terraform #DevOps #CloudEngineering #InfrastructureAsCode #ACM #CloudSecurity #SRE #PlatformEngineering</p>
]]></content:encoded></item><item><title><![CDATA[Overcoming GitHub’s 100 MB File‑Size Limit in Terraform Projects]]></title><description><![CDATA[While pushing my Terraform infrastructure code to GitHub, I encountered a frustrating error: “File terraform‑provider‑aws_v6.67.0_x5.exe exceeds GitHub’s…]]></description><link>https://mokri.hashnode.dev/overcoming-github-s-100-mb-file-size-limit-in-terraform-projects</link><guid isPermaLink="true">https://mokri.hashnode.dev/overcoming-github-s-100-mb-file-size-limit-in-terraform-projects</guid><dc:creator><![CDATA[Mohan Geddada]]></dc:creator><pubDate>Mon, 12 Oct 2026 02:50:24 GMT</pubDate><content:encoded><![CDATA[<h3><strong>🧩 The Challenge</strong></h3>
<p>While pushing my <strong>Terraform infrastructure code</strong> to GitHub, I encountered a frustrating error:</p>
<blockquote>
<p><em>“File terraform‑provider‑aws_v6.67.0_x5.exe exceeds GitHub’s 100 MB file‑size limit.”</em></p>
</blockquote>
<p>Terraform automatically downloads provider binaries into the .terraform directory, and these files can easily exceed GitHub’s upload limit. Even after adding a .gitignore, Git had already committed those large files, causing repeated push failures.</p>
<h3><strong>⚙️ My Project Setup</strong></h3>
<p>Inside my infrastructure folder (roboshop‑dev‑infra), I had multiple Terraform modules:</p>
<p>Code</p>
<pre><code class="language-plaintext">00-vpc/
10-sg/
20-sg-rules/
30-bastion/
40-databases/
.gitignore
.gitattributes 
</code></pre>
<p>Each module contained its own <a href="http://main.tf">main.tf</a>, <a href="http://variables.tf">variables.tf</a>, and terraform.lock.hcl.</p>
<h3>🧾 The Initial Attempt I tried re‑initializing the repository:</h3>
<p>bash</p>
<pre><code class="language-plaintext">cd roboshop-dev-infra/
rm -rf .git
git init
git branch -M main
git remote add origin https://github.com/mokridevops/roboshop-dev-infra.git
git add .
git commit -m "updated"
git push origin main 
</code></pre>
<p>But GitHub rejected the push because the large provider binaries were already tracked.</p>
<p>🧠 The Root Cause Even though I added the following patterns to .gitignore, the oversized files had already been committed:</p>
<p>bash</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa2ed5136fd4c5ce1e071dc/3c7418e5-44f2-4bfc-b7dd-899988f9f903.png" alt="" />

<p><img src="align=%22center%22" alt="" /></p>
<p>Git doesn’t retroactively untrack files that were committed before .gitignore was updated.</p>
<p>🛠️ The Fix</p>
<p>To resolve this, I created a new folder and initialized a fresh Git repository:</p>
<p>bash</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa2ed5136fd4c5ce1e071dc/99f7fa39-7d50-4e0c-84b0-40878f4f3679.png" alt="" />

<p>Before committing, I ensured .gitignore contained all Terraform‑related exclusions. Then I committed and pushed again:</p>
<p>bash</p>
<pre><code class="language-plaintext">git add .
git commit -m "created infra v1"
git push origin main 
</code></pre>
<p>✅ <strong>This time it worked perfectly!</strong></p>
<p>🧩 Why This Works</p>
<ul>
<li><p><code>The new repo starts clean, without previously tracked large files.</code></p>
</li>
<li><p><code>.gitignore prevents Terraform binaries and state files from being added.</code></p>
</li>
<li><p><code>Only essential configuration files (.tf, .tfvars, .hcl, .sh) are committed.</code></p>
</li>
</ul>
<p>🌟 Final Outcome</p>
<p>After re‑initializing and cleaning up, I successfully pushed my Terraform infrastructure code to GitHub without hitting the file‑size limit. This experience reinforced the importance of proper .gitignore management and repository hygiene in DevOps workflows.</p>
]]></content:encoded></item><item><title><![CDATA[Solved a Real‑World AWS Networking Issue: A Deep Cloud & DevOps Troubleshooting Win]]></title><description><![CDATA[Every once in a while, a cloud issue shows up that looks simple on the surface but ends up teaching you more than any certification course ever could. This…]]></description><link>https://mokri.hashnode.dev/solved-a-real-world-aws-networking-issue-a-deep-cloud-devops-troubleshooting-win</link><guid isPermaLink="true">https://mokri.hashnode.dev/solved-a-real-world-aws-networking-issue-a-deep-cloud-devops-troubleshooting-win</guid><dc:creator><![CDATA[Mohan Geddada]]></dc:creator><pubDate>Fri, 11 Sep 2026 19:27:38 GMT</pubDate><content:encoded><![CDATA[<p>Every once in a while, a cloud issue shows up that looks simple on the surface but ends up teaching you more than any certification course ever could. This is one of those stories — a real EC2‑to‑EC2 connectivity failure inside AWS that pushed me to troubleshoot across every layer of the stack.</p>
<p>It started with a basic requirement:<br /><strong>Server A needed to connect to MySQL running on Server B over a private VPC network.</strong></p>
<p>Everything <em>looked</em> perfect.</p>
<ul>
<li><p>Same VPC</p>
</li>
<li><p>Same subnet</p>
</li>
<li><p>Same Availability Zone</p>
</li>
<li><p>Security Groups open</p>
</li>
<li><p>NACLs open</p>
</li>
<li><p>MySQL running</p>
</li>
</ul>
<p>And yet… every connection attempt timed out.</p>
<p>This is the kind of problem that forces you to slow down, think systematically, and peel back each layer until the truth reveals itself.</p>
<hr />
<h2><strong>The Problem: MySQL Was Completely Unreachable</strong></h2>
<p>Server A simply couldn’t reach Server B’s private IP.<br /><code>ping</code> failed.<br /><code>nc -zv</code> timed out.<br />MySQL refused to respond.</p>
<p>When both ping and nc fail, the issue is no longer the application — it’s the network path itself.</p>
<p>So I began troubleshooting layer by layer.</p>
<hr />
<h1><strong>Step 1: Application Layer — MySQL Was Listening Only on IPv6</strong></h1>
<p>From the host:</p>
<blockquote>
<p>“tcp6 :::3306 LISTEN”</p>
</blockquote>
<p>That was the first red flag.<br />VPC communication uses <strong>IPv4 private IPs</strong>, so an IPv6‑only listener is effectively invisible.</p>
<p><strong>Fix:</strong><br />I updated MySQL’s configuration:</p>
<pre><code class="language-plaintext">bind-address = 0.0.0.0
</code></pre>
<p>After restart:</p>
<blockquote>
<p>“tcp 0.0.0.0:3306 LISTEN”</p>
</blockquote>
<p>Application layer cleared.</p>
<hr />
<h1><strong>Step 2: OS Layer — Host Firewall Ruled Out</strong></h1>
<p>I checked both firewalld and iptables:</p>
<ul>
<li><p>firewalld → inactive</p>
</li>
<li><p>iptables → ACCEPT on INPUT, FORWARD, OUTPUT</p>
</li>
</ul>
<p>No host‑level firewall was interfering.</p>
<p>This matters because OS firewalls can silently drop packets even when AWS networking is perfectly configured.</p>
<hr />
<h1><strong>Step 3: AWS Security Groups — All Good</strong></h1>
<p>Inbound:</p>
<ul>
<li><p>Port 3306 allowed</p>
</li>
<li><p>Source: 0.0.0.0/0 + Server A’s private IP</p>
</li>
</ul>
<p>Outbound:</p>
<ul>
<li>All traffic allowed</li>
</ul>
<p>Security Groups are stateful, but both directions still need to allow the traffic you expect. Everything checked out.</p>
<hr />
<h1><strong>Step 4: AWS NACLs — Also Good</strong></h1>
<p>Inbound: ALLOW ALL<br />Outbound: ALLOW ALL</p>
<p>NACLs are stateless — return traffic is not automatic — but in this case, both directions were fully open.</p>
<hr />
<h1><strong>Step 5: Subnet &amp; Availability Zone — Verified</strong></h1>
<p>Both servers were in:</p>
<ul>
<li><p><strong>us‑east‑1a</strong></p>
</li>
<li><p><strong>subnet‑0c4c44c9d55e260e4</strong></p>
</li>
</ul>
<p>Subnets are AZ‑specific, so comparing IDs (not names) is critical. No mismatch here.</p>
<hr />
<h1><strong>Step 6: Connectivity Tests — Both Failed</strong></h1>
<ul>
<li><p><code>ping 172.31.11.193</code> → no replies</p>
</li>
<li><p><code>nc -zv 172.31.11.193 3306</code> → timeout</p>
</li>
</ul>
<p>At this point, the application, OS, SGs, NACLs, and subnet were all correct.</p>
<p>Only one layer remained: <strong>routing</strong>.</p>
<hr />
<h1><strong>Step 7: The Real Fix — A Missing VPC‑Local Route</strong></h1>
<p>This was the “aha” moment.</p>
<p>Using EC2 instance metadata, I inspected the route table associated with Server A’s subnet.</p>
<p>The route that should <em>always</em> be present was missing:</p>
<blockquote>
<p>“172.31.0.0/16 → local”<br /><strong>MISSING</strong></p>
</blockquote>
<p>This single missing route explained everything:</p>
<ul>
<li><p>No private IP communication</p>
</li>
<li><p>All internal traffic dropped</p>
</li>
<li><p>Only internet‑bound traffic worked</p>
</li>
</ul>
<p>Even though both servers lived inside the same VPC, Server A had <strong>no internal path</strong> to reach Server B.</p>
<hr />
<h1><strong>Final Fix: Add the VPC‑Local Route</strong></h1>
<p>I added the missing route:</p>
<ul>
<li><p><strong>Destination:</strong> 172.31.0.0/16</p>
</li>
<li><p><strong>Target:</strong> local</p>
</li>
</ul>
<p>Instantly, everything came back to life:</p>
<pre><code class="language-plaintext">nc -zv 172.31.11.193 3306
Connected!
</code></pre>
<p>MySQL login succeeded.<br />Private EC2‑to‑EC2 communication fully restored.</p>
<hr />
<h1><strong>Before &amp; After: What Actually Happened</strong></h1>
<h3><strong>Before Fix — Broken Private Network</strong></h3>
<p>Server A’s route table only had:</p>
<ul>
<li><code>0.0.0.0/0 → igw</code></li>
</ul>
<p>It was missing:</p>
<ul>
<li><code>172.31.0.0/16 → local</code></li>
</ul>
<p>Result:<br />Packets had <strong>no internal route</strong> inside the VPC.<br />Everything timed out.</p>
<h3><strong>After Fix — Private Path Restored</strong></h3>
<p>Once the local route was added:</p>
<ul>
<li><p>Internal routing worked end‑to‑end</p>
</li>
<li><p>MySQL became reachable</p>
</li>
<li><p>Ping and nc succeeded</p>
</li>
</ul>
<p>A single missing route caused a full outage.</p>
<hr />
<h1><strong>Key Takeaway: Troubleshoot Layer by Layer</strong></h1>
<p>This experience reinforced a powerful lesson:</p>
<p><strong>Cloud troubleshooting is never guesswork — it’s a systematic, multi‑layer process.</strong></p>
<ul>
<li><p>Application</p>
</li>
<li><p>OS</p>
</li>
<li><p>Security Groups</p>
</li>
<li><p>NACLs</p>
</li>
<li><p>Subnet</p>
</li>
<li><p>Connectivity</p>
</li>
<li><p>Routing</p>
</li>
</ul>
<p>And above all:</p>
<p><strong>EC2 metadata is the source of truth.<br />Never assume the AWS console tells the full story.</strong></p>
<p>This was a proud DevOps learning moment — and a checklist I’ll reuse for every future outage.</p>
]]></content:encoded></item><item><title><![CDATA[The Day AWS CLI Went Silent — And What It Taught Me About EC2 Networking]]></title><description><![CDATA[There are days in DevOps when everything works smoothly… and then there are days when AWS decides to test your patience, your skills, and your…]]></description><link>https://mokri.hashnode.dev/the-day-aws-cli-went-silent-and-what-it-taught-me-about-ec2-networking</link><guid isPermaLink="true">https://mokri.hashnode.dev/the-day-aws-cli-went-silent-and-what-it-taught-me-about-ec2-networking</guid><dc:creator><![CDATA[Mohan Geddada]]></dc:creator><pubDate>Fri, 11 Sep 2026 18:48:45 GMT</pubDate><content:encoded><![CDATA[<p>There are days in DevOps when everything works smoothly… and then there are days when AWS decides to test your patience, your skills, and your understanding of how its networking layers really behave.</p>
<p>Recently, I ran into one of those moments.</p>
<p>I was working inside an EC2 instance and needed to launch another EC2 instance using AWS CLI. Simple task, right? Except every AWS CLI command I ran — from <code>sts get-caller-identity</code> to <code>ec2 describe-security-groups</code> — returned absolutely <strong>nothing</strong>.</p>
<p>No JSON.<br />No error.<br />No text.<br />Just a silent return to the shell prompt.</p>
<p>This wasn’t a failure. It was worse: <strong>a non‑response</strong>.</p>
<p>And that kicked off one of the most interesting debugging sessions I’ve had in a while.</p>
<hr />
<h2>🔍 <strong>The Mystery: AWS CLI Commands Returning No Output</strong></h2>
<p>When AWS CLI fails, it usually tells you:</p>
<ul>
<li><p>“Unable to locate credentials”</p>
</li>
<li><p>“You must specify a region”</p>
</li>
<li><p>“AccessDenied”</p>
</li>
<li><p>“Endpoint connection timed out”</p>
</li>
</ul>
<p>But this time?<br />Nothing. Not even an error message.</p>
<p>That meant the problem wasn’t IAM, wasn’t region, wasn’t CLI installation — something deeper was happening.</p>
<p>So I started peeling the layers.</p>
<hr />
<h2>🧪 Step 1 — Verify AWS CLI Installation</h2>
<p>I checked:</p>
<pre><code class="language-plaintext">which aws
aws --version
</code></pre>
<p>Everything looked perfect. AWS CLI was installed and executable.</p>
<p>So the binary wasn’t corrupted.</p>
<hr />
<h2>🧪 Step 2 — Test Internet Connectivity</h2>
<p>I tried:</p>
<pre><code class="language-plaintext">wget https://aws.amazon.com
</code></pre>
<p>It worked beautifully. DNS resolution was fine. Outbound internet was fine.</p>
<p>So the instance wasn’t isolated.</p>
<hr />
<h2>🧪 Step 3 — Test AWS API Endpoint Connectivity</h2>
<p>This is where things got interesting.</p>
<p>I ran:</p>
<pre><code class="language-plaintext">curl https://sts.amazonaws.com
curl https://ec2.amazonaws.com
</code></pre>
<p>Both commands returned <strong>nothing</strong>.</p>
<p>Not an error.<br />Not a timeout.<br />Not even HTML.</p>
<p>Just silence.</p>
<p>This told me something very specific:</p>
<p>👉 My EC2 instance could reach <strong>public websites</strong>,<br />but could NOT reach <strong>AWS API endpoints</strong>.</p>
<p>That’s a huge clue.</p>
<hr />
<h2>🧩 <strong>The Root Cause: Outbound HTTPS Traffic Was Blocked</strong></h2>
<p>AWS CLI communicates with AWS services using HTTPS (port 443).<br />If outbound HTTPS is blocked, AWS CLI simply cannot talk to AWS.</p>
<p>And that’s exactly what was happening.</p>
<p>The EC2 instance’s <strong>security group outbound rules were too restrictive</strong>.</p>
<p>Even though inbound rules were fine, outbound rules were silently blocking AWS API calls.</p>
<p>Once I updated the outbound rule to:</p>
<pre><code class="language-plaintext">Type: HTTPS
Port: 443
Destination: 0.0.0.0/0
</code></pre>
<p>everything changed instantly.</p>
<hr />
<h2>🎉 <strong>The Breakthrough</strong></h2>
<p>I ran:</p>
<pre><code class="language-plaintext">aws sts get-caller-identity
</code></pre>
<p>And finally saw:</p>
<pre><code class="language-json">{
    "UserId": "AIDAZRHYHRONASSESAPVL",
    "Account": "655503100826",
    "Arn": "arn:aws:iam::655503100826:user/shell_user"
}
</code></pre>
<p>AWS CLI was alive again.</p>
<p>Curl started returning XML.<br />EC2 commands started working.<br />The instance could finally talk to AWS APIs.</p>
<hr />
<h2>🧠 <strong>What This Taught Me</strong></h2>
<p>This issue was a great reminder of how AWS networking layers interact:</p>
<h3>✔ Security groups affect outbound traffic</h3>
<p>Even though they’re stateful, outbound rules still matter.</p>
<h3>✔ Public internet ≠ AWS API access</h3>
<p>Reaching <code>aws.amazon.com</code> doesn’t mean you can reach <code>sts.amazonaws.com</code>.</p>
<h3>✔ AWS CLI silence is a networking symptom</h3>
<p>When AWS CLI returns nothing, it’s often because the API endpoint never responded.</p>
<h3>✔ DevOps troubleshooting is layered</h3>
<p>You need to check:</p>
<ul>
<li><p>CLI installation</p>
</li>
<li><p>IAM credentials</p>
</li>
<li><p>DNS</p>
</li>
<li><p>VPC routing</p>
</li>
<li><p>Security groups</p>
</li>
<li><p>API endpoint reachability</p>
</li>
</ul>
<p>One missing piece can break the entire chain.</p>
<hr />
<h2>🛠 <strong>Final Fix</strong></h2>
<p>To restore AWS CLI functionality:</p>
<ul>
<li><p>I tightened outbound rules to <strong>HTTPS 443 → 0.0.0.0/0</strong></p>
</li>
<li><p>Verified AWS API connectivity with <code>curl</code></p>
</li>
<li><p>Re-tested AWS CLI commands</p>
</li>
<li><p>Confirmed IAM identity and EC2 access</p>
</li>
</ul>
<p>Everything worked perfectly.</p>
<hr />
<h2>📌 <strong>Conclusion</strong></h2>
<p>This wasn’t just a networking issue — it was a great real‑world example of how DevOps requires thinking across multiple AWS layers simultaneously.</p>
<p>A silent AWS CLI isn’t a broken CLI.<br />It’s a sign that your EC2 instance can’t reach AWS itself.</p>
<p>And sometimes, the fix is as simple as allowing outbound HTTPS.</p>
]]></content:encoded></item></channel></rss>