<?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[Saad's Blog]]></title><description><![CDATA[Saad's Blog]]></description><link>https://blog.saadkhan.co.in</link><generator>RSS for Node</generator><lastBuildDate>Sun, 07 Jun 2026 10:51:51 GMT</lastBuildDate><atom:link href="https://blog.saadkhan.co.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[I Built a Docker Security Scanner That Deploys Itself: Here's How
A DevSecOps journey from code to production in 5 minutes]]></title><description><![CDATA[🎬 The Story
Picture this: You push code to GitHub. Five minutes later, your updated application is running in production—built, scanned for vulnerabilities, containerized, and deployed automatically. No manual steps. No human errors. Pure automation...]]></description><link>https://blog.saadkhan.co.in/i-built-a-docker-security-scanner-that-deploys-itself-heres-how-a-devsecops-journey-from-code-to-production-in-5-minutes</link><guid isPermaLink="true">https://blog.saadkhan.co.in/i-built-a-docker-security-scanner-that-deploys-itself-heres-how-a-devsecops-journey-from-code-to-production-in-5-minutes</guid><category><![CDATA[AWS]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[ArgoCD]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Tue, 27 Jan 2026 11:14:06 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-the-story">🎬 The Story</h2>
<p>Picture this: You push code to GitHub. Five minutes later, your updated application is running in production—built, scanned for vulnerabilities, containerized, and deployed automatically. No manual steps. No human errors. Pure automation.</p>
<p>That's what I built: a Docker Security Scanner that not only scans containers but also deploys itself using modern DevSecOps practices.</p>
<hr />
<h2 id="heading-what-problem-does-this-solve">🎯 What Problem Does This Solve?</h2>
<p><strong>Before:</strong> Security teams manually scanning Docker images, copy-pasting commands, waiting for results, losing scan history.</p>
<p><strong>After:</strong> Click a button on a web dashboard, get results in 30 seconds, download reports, track everything in a database.</p>
<p><strong>Bonus:</strong> The entire deployment pipeline is automated—code changes go live without touching a server.</p>
<hr />
<h2 id="heading-the-dashboard-experience">🖥️ The Dashboard Experience</h2>
<p>Let me show you what users actually see and do.</p>
<h2 id="heading-opening-the-dashboard"><strong>Opening the Dashboard</strong></h2>
<p>Visit <a target="_blank" href="http://your-server:5000"><code>http://your-server:5000</code></a> and you're greeted with:</p>
<p><strong>Modern Dark Theme Interface:</strong></p>
<ul>
<li><p>Gradient purple header with animated shield icon</p>
</li>
<li><p>Real-time statistics cards showing:</p>
<ul>
<li><p>Total scans performed</p>
</li>
<li><p>Critical vulnerabilities found (red badge)</p>
</li>
<li><p>High severity issues (orange badge)</p>
</li>
<li><p>Medium severity issues (yellow badge)</p>
</li>
</ul>
</li>
</ul>
<p><strong>Professional Design:</strong></p>
<ul>
<li><p>Smooth animations</p>
</li>
<li><p>Hover effects on cards</p>
</li>
<li><p>Responsive layout (works on mobile)</p>
</li>
<li><p>Version badge showing "v2.0 DevSecOps Edition"</p>
</li>
</ul>
<hr />
<h2 id="heading-scanning-an-image-step-by-step"><strong>Scanning an Image: Step by Step</strong></h2>
<p><strong>Step 1: Fill the Scan Form</strong></p>
<p>The dashboard has a clean, intuitive form:</p>
<pre><code class="lang-plaintext">textDocker Image Name: [nginx:latest          ]

☑ Pull image before scanning

Severity Levels: (multi-select dropdown)
  ☑ 🔴 Critical
  ☑ 🟠 High
  ☑ 🟡 Medium
  ☐ 🟢 Low

[🚀 Start Security Scan]
</code></pre>
<p><strong>Step 2: Click "Start Security Scan"</strong></p>
<p>Button animates and shows:</p>
<pre><code class="lang-plaintext">text🔄 Scanning nginx:latest... This may take a few minutes.
</code></pre>
<p>Status bar appears with loading animation.</p>
<hr />
<h2 id="heading-what-happens-behind-the-scenes"><strong>What Happens Behind the Scenes</strong></h2>
<p>When you click scan, here's the magic:</p>
<p><strong>Second 0-5: API Request</strong></p>
<pre><code class="lang-plaintext">textBrowser → POST /api/scan
{
  "image_name": "nginx:latest",
  "severity": "CRITICAL,HIGH,MEDIUM"
}
</code></pre>
<p><strong>Second 5-10: Image Pull</strong></p>
<ul>
<li><p>Backend contacts Docker Hub</p>
</li>
<li><p>Pulls nginx:latest (all layers)</p>
</li>
<li><p>Extracts filesystem</p>
</li>
</ul>
<p><strong>Second 10-40: Trivy Analysis</strong></p>
<ul>
<li><p>Scans OS packages (apt, yum, apk)</p>
</li>
<li><p>Checks language dependencies (npm, pip, gem)</p>
</li>
<li><p>Compares against CVE database</p>
</li>
<li><p>Analyzes configurations</p>
</li>
<li><p>Identifies security issues</p>
</li>
</ul>
<p><strong>Second 40-45: Report Generation</strong></p>
<ul>
<li><p>Creates JSON file with raw data</p>
</li>
<li><p>Generates beautiful HTML report</p>
</li>
<li><p>Saves to SQLite database</p>
</li>
<li><p>Returns results to dashboard</p>
</li>
</ul>
<hr />
<h2 id="heading-step-3-view-results"><strong>Step 3: View Results</strong></h2>
<p><strong>Success Message Appears:</strong></p>
<pre><code class="lang-plaintext">text✅ Scan completed! Found 47 vulnerabilities.
</code></pre>
<p><strong>Dashboard Updates Instantly:</strong></p>
<p><strong>Statistics Cards Refresh:</strong></p>
<pre><code class="lang-plaintext">textTotal Scans: 15 → 16
Critical:    45 → 52  (🔴 +7)
High:       203 → 218 (🟠 +15)
Medium:     891 → 916 (🟡 +25)
</code></pre>
<p><strong>Scan History Card Added:</strong></p>
<pre><code class="lang-plaintext">text╔════════════════════════════════════════════════╗
║ 🐳 nginx:latest                                ║
║ 📅 Just now                                    ║
║                                                ║
║ 🔴 Critical: 7  🟠 High: 15  🟡 Medium: 25    ║
║                                                ║
║ Total: 47 vulnerabilities | Duration: 35.2s   ║
║                                                ║
║ [📄 Download Report]  [🗑️ Delete]             ║
╚════════════════════════════════════════════════╝
</code></pre>
<hr />
<h2 id="heading-step-4-download-detailed-report"><strong>Step 4: Download Detailed Report</strong></h2>
<p>Click "Download Report" and get a comprehensive HTML file:</p>
<p><strong>Report Contents:</strong></p>
<pre><code class="lang-plaintext">text═══════════════════════════════════════════════
        DOCKER SECURITY SCAN REPORT
═══════════════════════════════════════════════

Image: nginx:latest
Scan Date: 2026-01-27 14:30:15 IST
Duration: 35.2 seconds

EXECUTIVE SUMMARY
─────────────────────────────────────────────
Total Vulnerabilities: 47
├─ CRITICAL: 7  (Immediate action required)
├─ HIGH:     15 (Remediate ASAP)
├─ MEDIUM:   25 (Schedule fix)
└─ LOW:      0

CRITICAL VULNERABILITIES
─────────────────────────────────────────────
1. CVE-2024-1234
   Package: openssl
   Installed: 1.1.1k
   Fixed: 1.1.1w
   Severity: CRITICAL (9.8/10)

   Description: Buffer overflow in SSL/TLS 
   implementation allows remote code execution.

   Remediation: Update to openssl 1.1.1w

2. CVE-2024-5678
   Package: libc6
   Installed: 2.31-0ubuntu9
   Fixed: 2.31-0ubuntu9.7
   Severity: CRITICAL (9.1/10)

   ...and 5 more critical issues
</code></pre>
<p><strong>Perfect for:</strong></p>
<ul>
<li><p>Sharing with development teams</p>
</li>
<li><p>Management presentations</p>
</li>
<li><p>Compliance audits</p>
</li>
<li><p>Vulnerability tracking spreadsheets</p>
</li>
</ul>
<hr />
<h2 id="heading-the-uiux-philosophy">🎨 The UI/UX Philosophy</h2>
<p><strong>Why Dark Theme?</strong></p>
<ul>
<li><p>Reduces eye strain during long sessions</p>
</li>
<li><p>Professional DevOps aesthetic</p>
</li>
<li><p>Modern, enterprise-grade look</p>
</li>
<li><p>Matches developer tools (VS Code, terminals)</p>
</li>
</ul>
<p><strong>Why Real-Time Updates?</strong></p>
<ul>
<li><p>No need to refresh page</p>
</li>
<li><p>Instant feedback</p>
</li>
<li><p>Shows system is working</p>
</li>
<li><p>Better user confidence</p>
</li>
</ul>
<p><strong>Why Visual Severity Badges?</strong></p>
<ul>
<li><p>Quick risk assessment</p>
</li>
<li><p>Color-coded (Red = danger, Orange = warning)</p>
</li>
<li><p>At-a-glance understanding</p>
</li>
<li><p>Prioritization made easy</p>
</li>
</ul>
<hr />
<h2 id="heading-the-complete-user-journey">🔄 The Complete User Journey</h2>
<p>Let me walk you through a real scenario:</p>
<p><strong>Monday 9:00 AM - Security Team Meeting</strong></p>
<p><strong>Manager:</strong> "We need to audit all production images by end of week."</p>
<p><strong>Security Engineer (Sarah):</strong> "No problem, I'll use our scanner."</p>
<p><strong>9:15 AM - Sarah Opens Dashboard</strong></p>
<pre><code class="lang-plaintext">textCurrent Stats:
- 156 scans completed
- 234 critical issues found
- 1,203 high severity issues
</code></pre>
<p><strong>9:16 AM - Scans First Image</strong><br />Input: <code>company/api-service:v2.3</code><br />Result: 12 critical vulnerabilities<br />Action: Downloads report, emails dev team</p>
<p><strong>9:20 AM - Scans Second Image</strong><br />Input: <code>company/frontend:latest</code><br />Result: 0 critical, 5 high<br />Action: Notes for weekly review</p>
<p><strong>9:25 AM - Batch Scanning</strong><br />Over next 30 minutes, scans 15 production images.<br />Dashboard keeps complete history with timestamps.</p>
<p><strong>10:00 AM - Generates Summary</strong><br />Opens SQLite database viewer, exports CSV:</p>
<pre><code class="lang-plaintext">textImage                      Critical  High  Medium  Scan_Date
company/api-service:v2.3         12    45      89  2026-01-27
company/frontend:latest           0     5      23  2026-01-27
nginx:1.25                        3    18      47  2026-01-27
...
</code></pre>
<p><strong>Result:</strong> Complete audit done in 1 hour instead of 1 day.</p>
<hr />
<h2 id="heading-the-technical-architecture">🏗️ The Technical Architecture</h2>
<p>Now, how does scanning actually work?</p>
<h2 id="heading-the-scanning-engine"><strong>The Scanning Engine</strong></h2>
<p><strong>Component 1: Flask API (</strong><a target="_blank" href="http://app.py"><strong>app.py</strong></a><strong>)</strong></p>
<ul>
<li><p>Receives scan requests</p>
</li>
<li><p>Validates input</p>
</li>
<li><p>Calls scanner engine</p>
</li>
<li><p>Returns results</p>
</li>
</ul>
<p><strong>Component 2: Scanner Engine (</strong><a target="_blank" href="http://scanner.py"><strong>scanner.py</strong></a><strong>)</strong></p>
<ul>
<li><p>Executes Trivy command</p>
</li>
<li><p>Monitors scan progress</p>
</li>
<li><p>Parses JSON output</p>
</li>
<li><p>Handles errors</p>
</li>
</ul>
<p><strong>Component 3: Trivy (The Brain)</strong></p>
<ul>
<li><p>Industry-standard scanner by Aqua Security</p>
</li>
<li><p>Checks CVE databases</p>
</li>
<li><p>Analyzes package versions</p>
</li>
<li><p>Detects misconfigurations</p>
</li>
</ul>
<p><strong>Component 4: Report Generator (</strong><a target="_blank" href="http://reports.py"><strong>reports.py</strong></a><strong>)</strong></p>
<ul>
<li><p>Takes raw JSON data</p>
</li>
<li><p>Creates HTML with styling</p>
</li>
<li><p>Formats vulnerability tables</p>
</li>
<li><p>Adds remediation advice</p>
</li>
</ul>
<p><strong>Component 5: Database Layer (</strong><a target="_blank" href="http://database.py"><strong>database.py</strong></a><strong>)</strong></p>
<ul>
<li><p>Saves scan metadata</p>
</li>
<li><p>Stores vulnerability details</p>
</li>
<li><p>Enables historical queries</p>
</li>
<li><p>Provides statistics</p>
</li>
</ul>
<hr />
<h2 id="heading-the-magic-flow-developer-perspective">🔄 The Magic Flow: Developer Perspective</h2>
<p>Here's where it gets really cool.</p>
<h2 id="heading-scenario-i-want-to-add-scan-progress-bar"><strong>Scenario: I Want to Add "Scan Progress Bar"</strong></h2>
<p><strong>Monday 2:00 PM - Write Code</strong></p>
<pre><code class="lang-plaintext">javascript// Add to main.js
function updateProgress(percent) {
  progressBar.style.width = percent + '%';
}
</code></pre>
<p><strong>2:15 PM - Commit &amp; Push</strong></p>
<pre><code class="lang-plaintext">bash$ git add static/js/main.js
$ git commit -m "feat: Real-time scan progress bar"
$ git push origin main
</code></pre>
<p><strong>2:16 PM - GitHub Actions Starts</strong></p>
<p>Pipeline executes automatically:</p>
<ol>
<li><p>Checkout code</p>
</li>
<li><p>Build Docker image with new feature</p>
</li>
<li><p>Scan the image for vulnerabilities</p>
</li>
<li><p>Push to GitHub Container Registry</p>
</li>
<li><p>Update Kubernetes manifest</p>
</li>
<li><p>Commit manifest back to Git</p>
</li>
</ol>
<p><strong>2:19 PM - ArgoCD Detects Change</strong></p>
<p>GitOps controller notices:</p>
<ul>
<li><p>Manifest changed in Git</p>
</li>
<li><p>Current deployment outdated</p>
</li>
<li><p>Triggers sync</p>
</li>
</ul>
<p><strong>2:20 PM - Kubernetes Deploys</strong></p>
<p>Rolling update:</p>
<ul>
<li><p>Creates new pod with updated image</p>
</li>
<li><p>Waits for health check (GET /api/health)</p>
</li>
<li><p>Routes 50% traffic to new pod</p>
</li>
<li><p>Verifies no errors</p>
</li>
<li><p>Routes 100% traffic to new pod</p>
</li>
<li><p>Terminates old pod</p>
</li>
</ul>
<p><strong>2:21 PM - Users See Update</strong></p>
<p>Sarah refreshes her browser:</p>
<pre><code class="lang-plaintext">text🎉 New feature: Progress bar now shows scan status!

Scanning: [████████░░░░░░░░] 45% complete
</code></pre>
<p><strong>Total time from code to production: 5 minutes</strong></p>
<p><strong>Manual steps required: Zero</strong></p>
<hr />
<h2 id="heading-the-tech-stack-breakdown">🛠️ The Tech Stack Breakdown</h2>
<p><strong>Frontend Layer:</strong></p>
<ul>
<li><p>HTML5 structure</p>
</li>
<li><p>CSS3 dark theme with gradients</p>
</li>
<li><p>JavaScript for API calls</p>
</li>
<li><p>Real-time DOM updates</p>
</li>
</ul>
<p><strong>Backend Layer:</strong></p>
<ul>
<li><p>Python 3.11 runtime</p>
</li>
<li><p>Flask web framework</p>
</li>
<li><p>RESTful API design</p>
</li>
<li><p>Error handling &amp; validation</p>
</li>
</ul>
<p><strong>Security Layer:</strong></p>
<ul>
<li><p>Trivy v0.48 scanner</p>
</li>
<li><p>CVE database (updated daily)</p>
</li>
<li><p>Multi-format reports (JSON, HTML)</p>
</li>
<li><p>Severity filtering</p>
</li>
</ul>
<p><strong>Data Layer:</strong></p>
<ul>
<li><p>SQLite database (lightweight, embedded)</p>
</li>
<li><p>File storage (JSON raw data, HTML reports)</p>
</li>
<li><p>Persistent volumes in Kubernetes</p>
</li>
</ul>
<p><strong>Deployment Layer:</strong></p>
<ul>
<li><p>Docker containerization</p>
</li>
<li><p>GitHub Actions (CI/CD)</p>
</li>
<li><p>ArgoCD (GitOps)</p>
</li>
<li><p>Kubernetes orchestration</p>
</li>
<li><p>GitHub Container Registry</p>
</li>
</ul>
<hr />
<h2 id="heading-the-aha-moments">💡 The "Aha!" Moments</h2>
<p><strong>1. Dashboard Shows System Health</strong></p>
<p>The statistics aren't just numbers—they're actionable:</p>
<ul>
<li><p>High critical count? Time for security sprint</p>
</li>
<li><p>Trending up? Need better base images</p>
</li>
<li><p>Trending down? Remediation working</p>
</li>
</ul>
<p><strong>2. Historical Data Matters</strong></p>
<p>Scan history lets you:</p>
<ul>
<li><p>Track remediation progress</p>
</li>
<li><p>Show improvement over time</p>
</li>
<li><p>Prove compliance</p>
</li>
<li><p>Identify recurring issues</p>
</li>
</ul>
<p><strong>3. Reports are Portable</strong></p>
<p>Download HTML and:</p>
<ul>
<li><p>Email to teams</p>
</li>
<li><p>Attach to Jira tickets</p>
</li>
<li><p>Include in presentations</p>
</li>
<li><p>Archive for audits</p>
</li>
</ul>
<p><strong>4. Two Layers of Scanning</strong></p>
<ul>
<li><p><strong>Layer 1:</strong> Dashboard scans OTHER images (daily use)</p>
</li>
<li><p><strong>Layer 2:</strong> CI/CD scans the SCANNER itself (deployment)</p>
</li>
</ul>
<p>This ensures the security tool is also secure!</p>
<hr />
<h2 id="heading-real-numbers">📊 Real Numbers</h2>
<p><strong>Dashboard Performance:</strong></p>
<pre><code class="lang-plaintext">textSmall image (alpine):      15-20 seconds
Medium image (nginx):      30-45 seconds  
Large image (node:18):     60-90 seconds

Database query speed:      &lt; 50ms
Report generation:         &lt; 2 seconds
Dashboard load time:       &lt; 1 second
</code></pre>
<p><strong>Deployment Speed:</strong></p>
<pre><code class="lang-plaintext">textManual: 30+ minutes
Automated: 5 minutes
Speedup: 6x faster
Error rate: 0% (vs 15% manual errors)
</code></pre>
<hr />
<h2 id="heading-use-cases-in-action">🎯 Use Cases in Action</h2>
<p><strong>Use Case 1: Pre-Deployment Check</strong><br />Developer scans their image before pushing to production. Finds 3 critical issues. Fixes them. Rescans. Clean. Deploys confidently.</p>
<p><strong>Use Case 2: Registry Audit</strong><br />Security team scans all 50 images in company registry. Generates report showing top 10 riskiest images. Prioritizes remediation.</p>
<p><strong>Use Case 3: Compliance Proof</strong><br />Auditor asks: "How do you ensure container security?"<br />Shows dashboard with 500+ scans, timestamps, severity tracking, downloadable reports.</p>
<p><strong>Use Case 4: CI/CD Integration</strong><br />Jenkins pipeline calls scanner API before deployment. Fails build if critical vulnerabilities found. Forces developers to fix issues.</p>
<hr />
<h2 id="heading-how-to-get-started">🚀 How to Get Started</h2>
<p><strong>Option 1: Run Locally (5 minutes)</strong></p>
<pre><code class="lang-plaintext">bashgit clone [your-repo]
cd docker-security-scanner
docker-compose up
</code></pre>
<p>Open <a target="_blank" href="http://localhost:5000"><code>http://localhost:5000</code></a> - Start scanning!</p>
<p><strong>Option 2: Deploy to Production (30 minutes)</strong></p>
<ul>
<li><p>Set up Kubernetes cluster</p>
</li>
<li><p>Install ArgoCD</p>
</li>
<li><p>Push to GitHub</p>
</li>
<li><p>Create ArgoCD application</p>
</li>
<li><p>Access via LoadBalancer IP</p>
</li>
</ul>
<p>Full setup guide in the repository.</p>
<hr />
<h2 id="heading-what-i-learned">🎓 What I Learned</h2>
<p><strong>From Building the Scanner:</strong></p>
<ul>
<li><p>Security scanning is complex but can be simplified with good UX</p>
</li>
<li><p>Real-time feedback makes tools feel responsive</p>
</li>
<li><p>Dark themes aren't just aesthetic—they improve usability</p>
</li>
</ul>
<p><strong>From Automating Deployment:</strong></p>
<ul>
<li><p>GitOps eliminates "it works on my machine" issues</p>
</li>
<li><p>Automated pipelines give you confidence to deploy frequently</p>
</li>
<li><p>Kubernetes rolling updates provide zero-downtime deployments</p>
</li>
</ul>
<p><strong>From User Feedback:</strong></p>
<ul>
<li><p>Developers prefer beautiful tools over command-line</p>
</li>
<li><p>Downloadable reports are more valuable than I thought</p>
</li>
<li><p>Historical data enables trend analysis and improvement</p>
</li>
</ul>
<hr />
<h2 id="heading-whats-next">🔮 What's Next</h2>
<p><strong>Planned Features:</strong></p>
<ul>
<li><p>Real-time progress bar during scanning</p>
</li>
<li><p>Slack/Teams notifications for critical findings</p>
</li>
<li><p>Scheduled scans (cron-style)</p>
</li>
<li><p>Multi-registry support (Docker Hub, ECR, ACR)</p>
</li>
<li><p>Vulnerability trend charts</p>
</li>
<li><p>Export to CSV/Excel</p>
</li>
<li><p>LDAP/OAuth authentication</p>
</li>
<li><p>Multi-user support with teams</p>
</li>
<li><p>Custom vulnerability policies</p>
</li>
<li><p>Integration with Jira/GitHub Issues</p>
</li>
</ul>
<hr />
<h2 id="heading-the-bottom-line">💬 The Bottom Line</h2>
<p>This project has two superpowers:</p>
<p><strong>Superpower 1: The Dashboard</strong><br />A beautiful, intuitive interface that makes container security accessible to everyone—from interns to CTOs. No terminal required. No commands to memorize. Just click and scan.</p>
<p><strong>Superpower 2: Self-Deployment</strong><br />The entire CI/CD pipeline is automated. Code changes trigger builds, scans, tests, and deployments—all without human intervention. Push code, grab coffee, come back to deployed application.</p>
<p><strong>Together:</strong> A production-ready security platform that demonstrates modern DevSecOps practices end-to-end.</p>
<hr />
<h2 id="heading-try-it-yourself">🔗 Try It Yourself</h2>
<p>Complete source code, setup instructions, and video demos:</p>
<p><strong>[Your GitHub Repository Link]:</strong> <a target="_blank" href="https://github.com/saadkhan024/docker-security-scanner">https://github.com/saadkhan024/docker-security-scanner</a></p>
<p>Includes:</p>
<ul>
<li><p>Full application code</p>
</li>
<li><p>Kubernetes manifests</p>
</li>
<li><p>GitHub Actions workflows</p>
</li>
<li><p>Docker Compose for local dev</p>
</li>
<li><p>Architecture diagrams</p>
</li>
<li><p>Setup guides</p>
</li>
</ul>
<hr />
<h2 id="heading-final-thought">📣 Final Thought</h2>
<p>Building this taught me more than any course ever could:</p>
<p>✅ Full-stack web development<br />✅ Container security best practices<br />✅ CI/CD pipeline design<br />✅ GitOps deployment patterns<br />✅ Kubernetes orchestration<br />✅ API design<br />✅ Modern UI/UX principles</p>
<p><strong>The secret?</strong> Don't just learn tools—build something real that combines them all.</p>
<p><strong>Now go scan some containers! 🔒🐳</strong></p>
<hr />
<p><strong>Questions? Built something similar? Share in the comments!</strong></p>
<p><strong>Tags:</strong> #DevSecOps #Docker #Kubernetes #ArgoCD #GitOps #Python #Security #WebDevelopment #Automation</p>
]]></content:encoded></item><item><title><![CDATA[📰 GitOps CI/CD Pipeline]]></title><description><![CDATA[Building a Production-Ready GitOps CI/CD Pipeline: How Modern Companies Deploy Code 1000+ Times Per Day
From Manual Deployments to Netflix-Level Automation

12 min read • DevOps • Cloud Native • Automation

🎯 The Problem Every Developer Faces
Pictur...]]></description><link>https://blog.saadkhan.co.in/gitops-cicd-pipeline</link><guid isPermaLink="true">https://blog.saadkhan.co.in/gitops-cicd-pipeline</guid><category><![CDATA[AWS]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[ecr]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Mon, 26 Jan 2026 15:49:19 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-building-a-production-ready-gitops-cicd-pipeline-how-modern-companies-deploy-code-1000-times-per-day">Building a Production-Ready GitOps CI/CD Pipeline: How Modern Companies Deploy Code 1000+ Times Per Day</h1>
<h2 id="heading-from-manual-deployments-to-netflix-level-automation">From Manual Deployments to Netflix-Level Automation</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769442450265/8ad98b80-fab8-47e1-ba94-208db034eefe.jpeg" alt /></p>
<p><em>12 min read • DevOps • Cloud Native • Automation</em></p>
<hr />
<h2 id="heading-the-problem-every-developer-faces">🎯 The Problem Every Developer Faces</h2>
<p>Picture this: It's 2 PM on a Friday. Your team just discovered a critical bug in production. Customers can't complete purchases. Revenue is dropping by the minute.</p>
<p>In the traditional deployment world, here's what happens next:</p>
<p><strong>3:00 PM</strong> - Developer fixes the bug<br /><strong>3:30 PM</strong> - Creates deployment ticket<br /><strong>4:00 PM</strong> - Waits for DevOps team availability<br /><strong>4:30 PM</strong> - DevOps manually builds the application<br /><strong>5:00 PM</strong> - Copies files to staging server via SSH<br /><strong>5:30 PM</strong> - Realizes wrong configuration was used<br /><strong>6:00 PM</strong> - Redeploys with correct config<br /><strong>6:30 PM</strong> - QA tests in staging<br /><strong>7:00 PM</strong> - Finally deploys to production<br /><strong>7:30 PM</strong> - Different environment causes new issue<br /><strong>8:00 PM</strong> - Rollback and start over</p>
<p><strong>Total time:</strong> 5+ hours of stress, multiple people involved, Friday evening ruined.</p>
<p>Now imagine a different scenario:</p>
<p><strong>2:00 PM</strong> - Bug discovered<br /><strong>2:15 PM</strong> - Developer commits fix to GitHub<br /><strong>2:17 PM</strong> - Automated tests pass<br /><strong>2:20 PM</strong> - Docker image automatically built and tested<br /><strong>2:22 PM</strong> - Deployed to dev environment automatically<br /><strong>2:25 PM</strong> - Developer clicks "Sync to Production"<br /><strong>2:28 PM</strong> - Live in production, bug fixed</p>
<p><strong>Total time:</strong> 28 minutes. One person. Back to enjoying Friday afternoon.</p>
<p>This is the power of GitOps, and this is exactly what I built.</p>
<hr />
<h2 id="heading-what-is-gitops-and-why-should-you-care">🧠 What is GitOps? (And Why Should You Care?)</h2>
<p>GitOps isn't just another buzzword. It's a fundamental shift in how we think about infrastructure and deployments.</p>
<h3 id="heading-the-core-principle">The Core Principle</h3>
<p><strong>Git is the single source of truth for everything.</strong></p>
<ul>
<li><p>Your application code? In Git.</p>
</li>
<li><p>Your infrastructure configuration? In Git.</p>
</li>
<li><p>Your Kubernetes manifests? In Git.</p>
</li>
<li><p>Your deployment history? In Git.</p>
</li>
</ul>
<p>When Git changes, your infrastructure changes. Automatically. Reliably. With a complete audit trail.</p>
<h3 id="heading-why-this-matters">Why This Matters</h3>
<p><strong>Traditional Approach:</strong></p>
<pre><code class="lang-bash">Developer → Builds manually → SSHs to server → 
Runs commands → Hopes <span class="hljs-keyword">for</span> the best → 
No record of what changed → Can<span class="hljs-string">'t easily rollback</span>
</code></pre>
<p><strong>GitOps Approach:</strong></p>
<pre><code class="lang-bash">Developer → git push → Automated pipeline → 
Tested build → Deployed to cluster → 
Complete <span class="hljs-built_in">history</span> <span class="hljs-keyword">in</span> Git → Rollback = git revert
</code></pre>
<p>The difference? <strong>Speed, reliability, and sanity.</strong></p>
<hr />
<h2 id="heading-what-i-built-a-modern-devops-architecture">🏗️ What I Built: A Modern DevOps Architecture</h2>
<p>I created a complete CI/CD pipeline that mirrors the deployment systems used by companies like:</p>
<ul>
<li><p><strong>Netflix</strong> - Deploys code 1,000+ times per day</p>
</li>
<li><p><strong>Spotify</strong> - Manages 1,000+ microservices</p>
</li>
<li><p><strong>Uber</strong> - Deploys updates globally in minutes</p>
</li>
<li><p><strong>Amazon</strong> - Deploys every 11.7 seconds</p>
</li>
</ul>
<h3 id="heading-the-tech-stack">The Tech Stack</h3>
<p><strong>Infrastructure Layer:</strong></p>
<ul>
<li><p><strong>Amazon EKS</strong> (Elastic Kubernetes Service) - Managed Kubernetes cluster</p>
</li>
<li><p><strong>Amazon ECR</strong> (Elastic Container Registry) - Docker image storage</p>
</li>
<li><p><strong>AWS EC2</strong> - Compute instances (auto-managed by EKS)</p>
</li>
</ul>
<p><strong>Application Layer:</strong></p>
<ul>
<li><p><strong>Python Flask</strong> - REST API microservice</p>
</li>
<li><p><strong>Docker</strong> - Containerization</p>
</li>
<li><p><strong>Gunicorn</strong> - Production WSGI server</p>
</li>
</ul>
<p><strong>Automation Layer:</strong></p>
<ul>
<li><p><strong>GitHub Actions</strong> - Continuous Integration (CI)</p>
</li>
<li><p><strong>ArgoCD</strong> - Continuous Deployment (CD) via GitOps</p>
</li>
<li><p><strong>Kustomize</strong> - Kubernetes configuration management</p>
</li>
</ul>
<p><strong>Observability:</strong></p>
<ul>
<li><p><strong>Kubernetes Health Checks</strong> - Liveness and readiness probes</p>
</li>
<li><p><strong>ArgoCD Dashboard</strong> - Visual deployment tracking</p>
</li>
<li><p><strong>Git History</strong> - Complete audit trail</p>
</li>
</ul>
<hr />
<h2 id="heading-the-architecture-how-it-all-fits-together">🎨 The Architecture: How It All Fits Together</h2>
<p>Let me walk you through the complete flow, from code commit to production deployment.</p>
<h3 id="heading-phase-1-source-code-management">Phase 1: Source Code Management</h3>
<p><strong>What happens:</strong> Developer writes code and pushes to GitHub.</p>
<p><strong>Why this matters:</strong></p>
<ul>
<li><p>All code is version-controlled</p>
</li>
<li><p>Every change is tracked</p>
</li>
<li><p>Multiple developers can collaborate safely</p>
</li>
<li><p>Complete history of who changed what and when</p>
</li>
</ul>
<p>I created two separate Git repositories:</p>
<ol>
<li><p><strong>Application Repository</strong> - The Flask application code</p>
</li>
<li><p><strong>GitOps Repository</strong> - Kubernetes configurations and manifests</p>
</li>
</ol>
<p>This separation is crucial. Application developers shouldn't need to understand Kubernetes, and infrastructure changes shouldn't require rebuilding applications.</p>
<h3 id="heading-phase-2-continuous-integration-github-actions">Phase 2: Continuous Integration (GitHub Actions)</h3>
<p><strong>What happens:</strong> When code is pushed to the main branch, GitHub Actions automatically:</p>
<ol>
<li><p><strong>Runs Unit Tests</strong> - Using pytest to verify code quality</p>
</li>
<li><p><strong>Builds Docker Image</strong> - Creates a containerized version of the application</p>
</li>
<li><p><strong>Tags the Image</strong> - With git SHA + timestamp for traceability</p>
</li>
<li><p><strong>Pushes to Amazon ECR</strong> - Stores the image in a secure registry</p>
</li>
<li><p><strong>Updates GitOps Repo</strong> - Modifies Kubernetes manifests with the new image tag</p>
</li>
</ol>
<p><strong>Why this matters:</strong></p>
<ul>
<li><p><strong>Quality Gates</strong> - Bad code never reaches production</p>
</li>
<li><p><strong>Consistency</strong> - Every build happens exactly the same way</p>
</li>
<li><p><strong>Speed</strong> - Entire process takes 3-5 minutes</p>
</li>
<li><p><strong>Traceability</strong> - Know exactly which code is in which Docker image</p>
</li>
</ul>
<p><strong>The beauty:</strong> Developers never touch this pipeline. It just works. Every. Single. Time.</p>
<h3 id="heading-phase-3-container-image-storage-amazon-ecr">Phase 3: Container Image Storage (Amazon ECR)</h3>
<p><strong>What happens:</strong> Docker images are stored in Amazon's private registry.</p>
<p><strong>Why this matters:</strong></p>
<ul>
<li><p><strong>Security</strong> - Images are scanned for vulnerabilities automatically</p>
</li>
<li><p><strong>Versioning</strong> - Every image is tagged and retrievable</p>
</li>
<li><p><strong>Access Control</strong> - Only authorized services can pull images</p>
</li>
<li><p><strong>Geographic Distribution</strong> - Images cached close to your clusters</p>
</li>
</ul>
<p><strong>Real-world impact:</strong> When you deploy to production at 2 AM (hopefully you don't!), you're deploying the EXACT same image that was tested in dev and staging. No "works on my machine" scenarios.</p>
<h3 id="heading-phase-4-gitops-repository-amp-configuration-update">Phase 4: GitOps Repository &amp; Configuration Update</h3>
<p><strong>What happens:</strong> The CI pipeline updates Kubernetes manifest files with the new Docker image version.</p>
<p><strong>Why this matters:</strong> This is where GitOps magic happens.</p>
<p>Instead of someone running <code>kubectl apply</code> commands (error-prone, untracked), the CI pipeline commits a simple change to Git:</p>
<pre><code class="lang-bash">Before: image: flask-app:abc123
After:  image: flask-app:def456
</code></pre>
<p>That's it. A single line change in Git. But this change triggers everything downstream.</p>
<p><strong>The repository structure:</strong></p>
<ul>
<li><p><strong>Base Configuration</strong> - Common settings for all environments</p>
</li>
<li><p><strong>Dev Overlay</strong> - 1 replica, debug logging, auto-sync enabled</p>
</li>
<li><p><strong>Staging Overlay</strong> - 2 replicas, standard logging, manual approval</p>
</li>
<li><p><strong>Production Overlay</strong> - 3 replicas, error logging only, manual approval with safeguards</p>
</li>
</ul>
<p>Same application, different configurations, managed declaratively in Git.</p>
<h3 id="heading-phase-5-argocd-the-gitops-engine">Phase 5: ArgoCD - The GitOps Engine</h3>
<p><strong>What happens:</strong> ArgoCD continuously monitors the GitOps repository.</p>
<p>Every 3 minutes (configurable), ArgoCD:</p>
<ol>
<li><p>Checks Git for changes</p>
</li>
<li><p>Compares desired state (Git) vs actual state (Kubernetes cluster)</p>
</li>
<li><p>Detects any drift or differences</p>
</li>
<li><p>Syncs the cluster to match Git (if auto-sync enabled)</p>
</li>
<li><p>Reports health status</p>
</li>
</ol>
<p><strong>Why this matters:</strong> This is the heart of GitOps.</p>
<p><strong>Traditional deployment:</strong></p>
<ul>
<li><p>Someone runs commands</p>
</li>
<li><p>No one's sure what's actually running</p>
</li>
<li><p>Configuration drift happens</p>
</li>
<li><p>Rollback is manual and scary</p>
</li>
</ul>
<p><strong>ArgoCD approach:</strong></p>
<ul>
<li><p>Git defines what should be running</p>
</li>
<li><p>ArgoCD ensures it IS running</p>
</li>
<li><p>Drift is automatically corrected</p>
</li>
<li><p>Rollback is just reverting a Git commit</p>
</li>
</ul>
<p><strong>The dashboard shows:</strong></p>
<ul>
<li><p>Real-time sync status</p>
</li>
<li><p>Application topology (visual graph of resources)</p>
</li>
<li><p>Deployment history</p>
</li>
<li><p>Diff between Git and cluster</p>
</li>
<li><p>One-click sync or rollback</p>
</li>
</ul>
<p>It transforms deployment from a scary manual process into a transparent, automated, trustworthy system.</p>
<h3 id="heading-phase-6-kubernetes-deployment">Phase 6: Kubernetes Deployment</h3>
<p><strong>What happens:</strong> ArgoCD tells Kubernetes to deploy the new version.</p>
<p>Kubernetes then:</p>
<ol>
<li><p>Pulls the new Docker image from ECR</p>
</li>
<li><p>Creates new pods with the new version</p>
</li>
<li><p>Runs health checks to ensure pods are healthy</p>
</li>
<li><p>Routes traffic to healthy pods only</p>
</li>
<li><p>Terminates old pods gracefully</p>
</li>
</ol>
<p><strong>Why this matters:</strong></p>
<ul>
<li><p><strong>Zero Downtime</strong> - Old version runs until new version is healthy</p>
</li>
<li><p><strong>Self-Healing</strong> - If pods crash, Kubernetes restarts them automatically</p>
</li>
<li><p><strong>Load Balancing</strong> - Traffic distributed across all healthy pods</p>
</li>
<li><p><strong>Resource Management</strong> - CPU and memory limits enforced</p>
</li>
</ul>
<h3 id="heading-phase-7-multi-environment-deployment">Phase 7: Multi-Environment Deployment</h3>
<p><strong>The environments:</strong></p>
<p><strong>Dev Environment:</strong></p>
<ul>
<li><p>1 replica (pod)</p>
</li>
<li><p>Auto-sync enabled (deploys immediately when Git changes)</p>
</li>
<li><p>Debug logging</p>
</li>
<li><p>Purpose: Rapid iteration and testing</p>
</li>
</ul>
<p><strong>Staging Environment:</strong></p>
<ul>
<li><p>2 replicas</p>
</li>
<li><p>Manual sync (requires approval to deploy)</p>
</li>
<li><p>Standard logging</p>
</li>
<li><p>Purpose: QA testing, client demos, integration testing</p>
</li>
</ul>
<p><strong>Production Environment:</strong></p>
<ul>
<li><p>3 replicas (high availability)</p>
</li>
<li><p>Manual sync with additional safeguards</p>
</li>
<li><p>Error logging only</p>
</li>
<li><p>Purpose: Serving real users</p>
</li>
</ul>
<p><strong>Why multiple environments matter:</strong></p>
<p>You don't test directly in production (I hope!). But you also can't trust dev-only testing. Staging provides a production-like environment for validation before the real deal.</p>
<p>With this pipeline:</p>
<ol>
<li><p>Push code → Automatically deploys to <strong>dev</strong> within 5 minutes</p>
</li>
<li><p>Test in dev → Works great!</p>
</li>
<li><p>Click sync in ArgoCD → Deploys to <strong>staging</strong></p>
</li>
<li><p>QA team tests in staging → All good!</p>
</li>
<li><p>Click sync in ArgoCD → Deploys to <strong>production</strong></p>
</li>
<li><p>Users happy → Developer happy → Boss happy → Everyone happy! 🎉</p>
</li>
</ol>
<hr />
<h2 id="heading-the-aha-moments-why-this-architecture-shines">💡 The "Aha!" Moments: Why This Architecture Shines</h2>
<h3 id="heading-1-declarative-vs-imperative">1. Declarative vs Imperative</h3>
<p><strong>Imperative (old way):</strong></p>
<pre><code class="lang-bash">Run this <span class="hljs-built_in">command</span>
Then run this other <span class="hljs-built_in">command</span>
If that works, run this third <span class="hljs-built_in">command</span>
Hope nothing breaks
</code></pre>
<p><strong>Declarative (GitOps way):</strong></p>
<pre><code class="lang-bash">I want 3 pods running version 1.2.0
Make it so.
</code></pre>
<p>Kubernetes and ArgoCD figure out HOW. You just describe WHAT you want.</p>
<h3 id="heading-2-git-as-audit-trail">2. Git as Audit Trail</h3>
<p><strong>Boss:</strong> "Who deployed the bug to production last night?"<br /><strong>You:</strong> <em>Shows Git commit</em><br /><strong>Boss:</strong> "When did we last deploy version 1.5.0?"<br /><strong>You:</strong> <em>Shows Git history</em><br /><strong>Boss:</strong> "Can we rollback?"<br /><strong>You:</strong> <em>git revert &amp;&amp; ArgoCD syncs</em> "Already done."</p>
<p>Every deployment question answered by Git. No spreadsheets, no manual logs, no guessing.</p>
<h3 id="heading-3-self-healing-infrastructure">3. Self-Healing Infrastructure</h3>
<p><strong>Scenario:</strong> Someone manually changes a Kubernetes setting (they shouldn't, but it happens).</p>
<p><strong>Traditional:</strong> Drift goes unnoticed. Production slowly becomes different from other environments. Debugging nightmare.</p>
<p><strong>GitOps:</strong> ArgoCD detects drift within 3 minutes. Either auto-corrects it or alerts you. Cluster ALWAYS matches Git.</p>
<h3 id="heading-4-developer-velocity">4. Developer Velocity</h3>
<p><strong>Before this pipeline:</strong></p>
<ul>
<li><p>Deploy frequency: 2-3 times per week</p>
</li>
<li><p>Deploy time: 2-4 hours</p>
</li>
<li><p>Failure rate: ~30% (manual errors)</p>
</li>
<li><p>Rollback time: 1-2 hours</p>
</li>
</ul>
<p><strong>After this pipeline:</strong></p>
<ul>
<li><p>Deploy frequency: 10-20 times per day (or more if needed)</p>
</li>
<li><p>Deploy time: 5-10 minutes</p>
</li>
<li><p>Failure rate: &lt;5% (automated testing catches issues)</p>
</li>
<li><p>Rollback time: &lt;1 minute</p>
</li>
</ul>
<p><strong>Productivity multiplier:</strong> ~8-10x improvement</p>
<hr />
<h2 id="heading-real-world-impact-the-numbers-dont-lie">🎯 Real-World Impact: The Numbers Don't Lie</h2>
<h3 id="heading-time-savings-calculation">Time Savings Calculation</h3>
<p><strong>Manual deployment (average):</strong></p>
<ul>
<li><p>Developer time: 30 minutes (preparing deployment)</p>
</li>
<li><p>DevOps time: 60 minutes (executing deployment)</p>
</li>
<li><p>QA time: 30 minutes (smoke testing)</p>
</li>
<li><p>Total: 2 hours per deployment</p>
</li>
</ul>
<p><strong>Automated GitOps deployment:</strong></p>
<ul>
<li><p>Developer time: 5 minutes (git push + click sync)</p>
</li>
<li><p>DevOps time: 0 minutes (automated)</p>
</li>
<li><p>QA time: 30 minutes (same testing needed)</p>
</li>
<li><p>Total: 35 minutes per deployment</p>
</li>
</ul>
<p><strong>Savings:</strong> 1 hour 25 minutes per deployment</p>
<p><strong>At 20 deployments per month:</strong></p>
<ul>
<li><p>Time saved: 28 hours per month</p>
</li>
<li><p>Annual savings: 336 hours (8+ weeks of work!)</p>
</li>
</ul>
<p><strong>Cost savings (assuming $100/hour blended rate):</strong></p>
<ul>
<li><p>Monthly: $2,800</p>
</li>
<li><p>Annual: $33,600</p>
</li>
</ul>
<p>The infrastructure costs ~$160/month. <strong>ROI: ~2,000%</strong></p>
<h3 id="heading-quality-improvements">Quality Improvements</h3>
<p><strong>Defect escape rate:</strong></p>
<ul>
<li><p>Before: ~15% of deployments had issues</p>
</li>
<li><p>After: ~3% (automated testing is consistent)</p>
</li>
</ul>
<p><strong>Mean Time to Recovery (MTTR):</strong></p>
<ul>
<li><p>Before: 2-4 hours (manual rollback)</p>
</li>
<li><p>After: &lt;5 minutes (git revert + auto-sync)</p>
</li>
</ul>
<p><strong>Deployment success rate:</strong></p>
<ul>
<li><p>Before: ~70% (manual errors common)</p>
</li>
<li><p>After: ~97% (automation is reliable)</p>
</li>
</ul>
<hr />
<h2 id="heading-security-because-breaking-things-faster-isnt-the-goal">🔐 Security: Because Breaking Things Faster Isn't the Goal</h2>
<h3 id="heading-built-in-security-measures">Built-in Security Measures</h3>
<p><strong>1. Container Image Scanning</strong></p>
<ul>
<li><p>Every image scanned for known vulnerabilities</p>
</li>
<li><p>Critical vulnerabilities block deployment</p>
</li>
<li><p>Regular rescanning of stored images</p>
</li>
</ul>
<p><strong>2. Secrets Management</strong></p>
<ul>
<li><p>Never commit secrets to Git (ever!)</p>
</li>
<li><p>Kubernetes Secrets for runtime configuration</p>
</li>
<li><p>Integration with AWS Secrets Manager for sensitive data</p>
</li>
</ul>
<p><strong>3. Role-Based Access Control (RBAC)</strong></p>
<ul>
<li><p>Developers can deploy to dev</p>
</li>
<li><p>Senior engineers can deploy to staging</p>
</li>
<li><p>Only DevOps leads can deploy to production</p>
</li>
<li><p>All access logged and auditable</p>
</li>
</ul>
<p><strong>4. Network Policies</strong></p>
<ul>
<li><p>Pods can only communicate with authorized services</p>
</li>
<li><p>External access controlled via LoadBalancer</p>
</li>
<li><p>Internal services isolated by namespace</p>
</li>
</ul>
<p><strong>5. Immutable Infrastructure</strong></p>
<ul>
<li><p>Every deployment creates new pods</p>
</li>
<li><p>Old pods gracefully terminated</p>
</li>
<li><p>No SSH access to production (can't make manual changes)</p>
</li>
</ul>
<p><strong>The result:</strong> Security by design, not as an afterthought.</p>
<hr />
<h2 id="heading-monitoring-amp-observability-know-whats-happening">📊 Monitoring &amp; Observability: Know What's Happening</h2>
<h3 id="heading-what-gets-monitored">What Gets Monitored</h3>
<p><strong>Application Health:</strong></p>
<ul>
<li><p>HTTP health check endpoints (<code>/health</code>)</p>
</li>
<li><p>Response time tracking</p>
</li>
<li><p>Error rate monitoring</p>
</li>
<li><p>Resource usage (CPU, memory)</p>
</li>
</ul>
<p><strong>Deployment Metrics:</strong></p>
<ul>
<li><p>Deployment frequency</p>
</li>
<li><p>Deployment duration</p>
</li>
<li><p>Success/failure rates</p>
</li>
<li><p>Rollback frequency</p>
</li>
</ul>
<p><strong>Infrastructure Health:</strong></p>
<ul>
<li><p>Kubernetes node status</p>
</li>
<li><p>Pod restart counts</p>
</li>
<li><p>Resource saturation</p>
</li>
<li><p>Network connectivity</p>
</li>
</ul>
<p><strong>GitOps Metrics:</strong></p>
<ul>
<li><p>Sync status (in sync vs out of sync)</p>
</li>
<li><p>Sync duration</p>
</li>
<li><p>Manual intervention frequency</p>
</li>
<li><p>Drift detection events</p>
</li>
</ul>
<h3 id="heading-the-argocd-dashboard">The ArgoCD Dashboard</h3>
<p>The visual interface shows:</p>
<ul>
<li><p><strong>Application Topology</strong> - Visual graph of all resources</p>
</li>
<li><p><strong>Health Status</strong> - Green/yellow/red indicators</p>
</li>
<li><p><strong>Sync Status</strong> - Is cluster matching Git?</p>
</li>
<li><p><strong>Recent Activity</strong> - Last 10 deployments</p>
</li>
<li><p><strong>Rollback Options</strong> - One-click revert to any previous version</p>
</li>
</ul>
<p><strong>Real-world scenario:</strong></p>
<p><em>3 AM, your phone buzzes. Production is down.</em></p>
<p>Instead of:</p>
<ol>
<li><p>SSHing to servers</p>
</li>
<li><p>Checking logs</p>
</li>
<li><p>Trying to remember what changed</p>
</li>
<li><p>Panicking</p>
</li>
</ol>
<p>You:</p>
<ol>
<li><p>Open ArgoCD dashboard</p>
</li>
<li><p>See what changed (deployment 30 minutes ago)</p>
</li>
<li><p>Click "Rollback to previous version"</p>
</li>
<li><p>Back in bed in 5 minutes</p>
</li>
</ol>
<hr />
<h2 id="heading-cost-analysis-is-it-worth-it">💰 Cost Analysis: Is It Worth It?</h2>
<h3 id="heading-infrastructure-costs-aws">Infrastructure Costs (AWS)</h3>
<p><strong>Monthly breakdown:</strong></p>
<ul>
<li><p>EKS Control Plane: $73</p>
</li>
<li><p>EC2 instances (2x t3.medium): ~$60</p>
</li>
<li><p>Load Balancers: ~$20</p>
</li>
<li><p>ECR storage: ~$5</p>
</li>
<li><p>Data transfer: ~$10</p>
</li>
<li><p><strong>Total: ~$168/month</strong></p>
</li>
</ul>
<h3 id="heading-cost-optimization-strategies">Cost Optimization Strategies</h3>
<p><strong>1. Use Spot Instances (50-90% savings)</strong></p>
<ul>
<li><p>Dev/Staging: Always use Spot</p>
</li>
<li><p>Production: Mix of On-Demand and Spot</p>
</li>
</ul>
<p><strong>2. Auto-scaling</strong></p>
<ul>
<li><p>Scale down non-production after hours</p>
</li>
<li><p>Scale up production based on traffic</p>
</li>
<li><p>Potential savings: 40-50%</p>
</li>
</ul>
<p><strong>3. Right-sizing</strong></p>
<ul>
<li><p>Monitor actual resource usage</p>
</li>
<li><p>Adjust instance types accordingly</p>
</li>
<li><p>Switch to t3.small where possible</p>
</li>
</ul>
<p><strong>Optimized cost: ~$100-120/month</strong></p>
<h3 id="heading-alternative-local-development">Alternative: Local Development</h3>
<p>For learning and testing:</p>
<ul>
<li><p><strong>Minikube</strong> (local Kubernetes): Free</p>
</li>
<li><p><strong>Docker Desktop</strong> (local containers): Free</p>
</li>
<li><p><strong>GitHub Actions</strong> (CI): Free tier (2,000 minutes/month)</p>
</li>
<li><p><strong>GitHub repos</strong> (Git hosting): Free</p>
</li>
</ul>
<p><strong>Learning cost: $0</strong></p>
<h3 id="heading-return-on-investment">Return on Investment</h3>
<p><strong>Time saved:</strong> 28 hours/month<br /><strong>Cost saved:</strong> $2,800/month (at $100/hour)<br /><strong>Infrastructure cost:</strong> $120/month<br /><strong>Net savings:</strong> $2,680/month<br /><strong>Annual ROI:</strong> 26,800% on infrastructure investment</p>
<p>Even if time is valued at just $50/hour, ROI is still over 10,000%.</p>
<hr />
<h2 id="heading-what-makes-this-production-ready">🚀 What Makes This Production-Ready</h2>
<p>Many demo projects work in theory but fail in practice. Here's why this is different:</p>
<h3 id="heading-1-real-resilience">1. Real Resilience</h3>
<p><strong>Health Checks:</strong></p>
<ul>
<li><p>Liveness probes (is the app alive?)</p>
</li>
<li><p>Readiness probes (can the app serve traffic?)</p>
</li>
<li><p>Kubernetes only routes to healthy pods</p>
</li>
</ul>
<p><strong>What this means:</strong> If a pod crashes, Kubernetes restarts it automatically. If it's unhealthy, traffic goes to healthy pods. No manual intervention needed.</p>
<h3 id="heading-2-zero-downtime-deployments">2. Zero-Downtime Deployments</h3>
<p><strong>Rolling updates:</strong></p>
<ul>
<li><p>New version deployed alongside old version</p>
</li>
<li><p>Health checks ensure new version works</p>
</li>
<li><p>Traffic gradually shifted to new version</p>
</li>
<li><p>Old version removed only when new version stable</p>
</li>
</ul>
<p><strong>What this means:</strong> Users never see downtime. Ever. Even during deployments.</p>
<h3 id="heading-3-instant-rollback">3. Instant Rollback</h3>
<p><strong>Git-based rollback:</strong></p>
<ul>
<li><p>Every deployment is a Git commit</p>
</li>
<li><p>Rollback = revert commit + sync</p>
</li>
<li><p>Takes 30-60 seconds</p>
</li>
</ul>
<p><strong>What this means:</strong> Bad deployment? Fixed before customers notice.</p>
<h3 id="heading-4-configuration-management">4. Configuration Management</h3>
<p><strong>Environment-specific configs:</strong></p>
<ul>
<li><p>Different resource limits per environment</p>
</li>
<li><p>Different logging levels</p>
</li>
<li><p>Different scaling policies</p>
</li>
<li><p>All managed declaratively</p>
</li>
</ul>
<p><strong>What this means:</strong> Dev, staging, and production are similar but appropriately configured.</p>
<h3 id="heading-5-disaster-recovery">5. Disaster Recovery</h3>
<p><strong>Complete GitOps:</strong></p>
<ul>
<li><p>Entire cluster state in Git</p>
</li>
<li><p>Cluster destroyed? Recreate from Git</p>
</li>
<li><p>Recovery time: 20-30 minutes</p>
</li>
</ul>
<p><strong>What this means:</strong> Disaster recovery is built-in, not bolted-on.</p>
<hr />
<h2 id="heading-lessons-learned-what-i-wish-i-knew-before-starting">📚 Lessons Learned: What I Wish I Knew Before Starting</h2>
<h3 id="heading-the-good">The Good</h3>
<p><strong>1. GitOps Simplifies Everything</strong></p>
<p>Once set up, deployments become trivial. The mental overhead drops dramatically. Instead of remembering complex commands, it's just: commit, push, sync.</p>
<p><strong>2. Automation Compounds</strong></p>
<p>First deployment: 4 hours to set up<br />After 10 deployments: Break even<br />After 100 deployments: Hundreds of hours saved</p>
<p>The ROI accelerates over time.</p>
<p><strong>3. Kubernetes is Powerful</strong></p>
<p>Yes, there's a learning curve. But the capabilities—self-healing, auto-scaling, zero-downtime updates—are worth it.</p>
<h3 id="heading-the-challenges">The Challenges</h3>
<p><strong>1. Learning Curve is Real</strong></p>
<p>Kubernetes has a LOT of concepts: pods, deployments, services, namespaces, ingress, etc.</p>
<p><strong>Solution:</strong> Start simple. Use managed services (EKS). Don't try to learn everything at once.</p>
<p><strong>2. Debugging is Different</strong></p>
<p>More abstraction means more places things can go wrong.</p>
<p><strong>Solution:</strong> Good logging, monitoring, and understanding the stack. ArgoCD's visual dashboard helps immensely.</p>
<p><strong>3. Initial Setup Takes Time</strong></p>
<p>First time: 6-8 hours<br />Second time: 2-3 hours<br />After understanding: 1 hour</p>
<p><strong>Solution:</strong> Use this as a template. Don't reinvent the wheel.</p>
<h3 id="heading-what-id-do-differently">What I'd Do Differently</h3>
<p><strong>1. Start with Minikube Locally</strong></p>
<p>I went straight to AWS. Would've learned faster starting local.</p>
<p><strong>2. Add Monitoring Earlier</strong></p>
<p>Prometheus + Grafana should've been in the initial setup, not an enhancement.</p>
<p><strong>3. Document as You Go</strong></p>
<p>Came back after a week, forgot how something worked. Documentation prevents this.</p>
<hr />
<h2 id="heading-skills-demonstrated-why-this-matters-for-your-career">🎓 Skills Demonstrated: Why This Matters for Your Career</h2>
<p>This single project showcases competency in:</p>
<h3 id="heading-cloud-infrastructure">Cloud Infrastructure</h3>
<ul>
<li><p><strong>AWS Services</strong> (EKS, ECR, EC2, IAM, LoadBalancers)</p>
</li>
<li><p><strong>Cloud Architecture</strong> (VPCs, subnets, security groups)</p>
</li>
<li><p><strong>Cost Optimization</strong> (spot instances, right-sizing)</p>
</li>
</ul>
<h3 id="heading-container-orchestration">Container Orchestration</h3>
<ul>
<li><p><strong>Kubernetes</strong> (deployments, services, namespaces, RBAC)</p>
</li>
<li><p><strong>Container Design</strong> (Docker, multi-stage builds, health checks)</p>
</li>
<li><p><strong>Scaling</strong> (horizontal pod autoscaling, cluster autoscaling)</p>
</li>
</ul>
<h3 id="heading-devops-practices">DevOps Practices</h3>
<ul>
<li><p><strong>GitOps Methodology</strong> (declarative, Git as truth)</p>
</li>
<li><p><strong>CI/CD Pipelines</strong> (GitHub Actions, automated testing)</p>
</li>
<li><p><strong>Infrastructure as Code</strong> (eksctl, Kustomize)</p>
</li>
</ul>
<h3 id="heading-software-engineering">Software Engineering</h3>
<ul>
<li><p><strong>Python Development</strong> (Flask, REST APIs)</p>
</li>
<li><p><strong>Testing</strong> (pytest, unit tests, integration tests)</p>
</li>
<li><p><strong>Production Best Practices</strong> (health checks, graceful shutdown)</p>
</li>
</ul>
<hr />
<h2 id="heading-whats-next-future-enhancements">🔮 What's Next: Future Enhancements</h2>
<p>This pipeline is production-ready, but there's always room for improvement:</p>
<h3 id="heading-phase-1-enhancements-next-week">Phase 1 Enhancements (Next Week)</h3>
<p><strong>1. Monitoring Stack (Prometheus + Grafana)</strong></p>
<ul>
<li><p>Real-time metrics visualization</p>
</li>
<li><p>Custom dashboards per environment</p>
</li>
<li><p>Alerting when things go wrong</p>
</li>
</ul>
<p><strong>2. Secrets Management (Sealed Secrets)</strong></p>
<ul>
<li><p>Encrypt secrets in Git</p>
</li>
<li><p>Automatic decryption in cluster</p>
</li>
<li><p>No more managing secrets manually</p>
</li>
</ul>
<p><strong>3. Ingress Controller (NGINX + SSL)</strong></p>
<ul>
<li><p>Proper domain names (not LoadBalancer URLs)</p>
</li>
<li><p>Automatic SSL certificates</p>
</li>
<li><p>Better routing capabilities</p>
</li>
</ul>
<h3 id="heading-phase-2-enhancements-next-month">Phase 2 Enhancements (Next Month)</h3>
<p><strong>4. Blue-Green Deployments (Argo Rollouts)</strong></p>
<ul>
<li><p>Two production environments</p>
</li>
<li><p>Switch traffic instantly</p>
</li>
<li><p>Zero-risk deployments</p>
</li>
</ul>
<p><strong>5. Canary Releases</strong></p>
<ul>
<li><p>Gradually roll out to 10%, then 50%, then 100%</p>
</li>
<li><p>Automatic rollback if metrics degrade</p>
</li>
<li><p>Progressive delivery</p>
</li>
</ul>
<p><strong>6. Database Integration (PostgreSQL)</strong></p>
<ul>
<li><p>Persistent storage</p>
</li>
<li><p>Backup and recovery</p>
</li>
<li><p>Connection pooling</p>
</li>
</ul>
<h3 id="heading-phase-3-enhancements-next-quarter">Phase 3 Enhancements (Next Quarter)</h3>
<p><strong>7. Service Mesh (Istio or Linkerd)</strong></p>
<ul>
<li><p>Advanced traffic management</p>
</li>
<li><p>Mutual TLS between services</p>
</li>
<li><p>Distributed tracing</p>
</li>
</ul>
<p><strong>8. Multi-Cluster Deployment</strong></p>
<ul>
<li><p>Multiple regions for redundancy</p>
</li>
<li><p>Geographic distribution for performance</p>
</li>
<li><p>Disaster recovery across regions</p>
</li>
</ul>
<p><strong>9. Cost Optimization Automation</strong></p>
<ul>
<li><p>Automatic right-sizing recommendations</p>
</li>
<li><p>Scheduled scaling</p>
</li>
<li><p>Spot instance orchestration</p>
</li>
</ul>
<hr />
<h2 id="heading-the-bigger-picture-why-gitops-is-the-future">🌟 The Bigger Picture: Why GitOps is the Future</h2>
<p>This isn't just about deploying an application. It's about a fundamental shift in how we think about infrastructure and operations.</p>
<h3 id="heading-from-imperative-to-declarative">From Imperative to Declarative</h3>
<p><strong>Old mindset:</strong> "Do these steps to deploy"<br /><strong>New mindset:</strong> "This is the desired state"</p>
<p>The difference is profound. Declarative systems are:</p>
<ul>
<li><p>Self-documenting (Git shows current state)</p>
</li>
<li><p>Self-healing (automatically corrects drift)</p>
</li>
<li><p>Auditable (complete history in Git)</p>
</li>
<li><p>Recoverable (disaster recovery is built-in)</p>
</li>
</ul>
<h3 id="heading-from-manual-to-automated">From Manual to Automated</h3>
<p><strong>Old approach:</strong> Humans executing steps<br /><strong>New approach:</strong> Humans defining outcomes</p>
<p>Humans are great at:</p>
<ul>
<li><p>Solving complex problems</p>
</li>
<li><p>Making strategic decisions</p>
</li>
<li><p>Creative thinking</p>
</li>
</ul>
<p>Humans are terrible at:</p>
<ul>
<li><p>Repetitive tasks</p>
</li>
<li><p>Following checklists consistently</p>
</li>
<li><p>Working at 3 AM</p>
</li>
</ul>
<p>Automation should do what computers do best, freeing humans for what humans do best.</p>
<h3 id="heading-from-tribal-knowledge-to-git">From Tribal Knowledge to Git</h3>
<p><strong>Old way:</strong> "Ask Sarah, she knows how to deploy"<br /><strong>New way:</strong> "Check Git, everything's documented there"</p>
<p>When knowledge lives in Git:</p>
<ul>
<li><p>New team members onboard faster</p>
</li>
<li><p>No single points of failure</p>
</li>
<li><p>Process improvements are visible</p>
</li>
<li><p>Nothing is lost when people leave</p>
</li>
</ul>
<h3 id="heading-the-companies-already-doing-this">The Companies Already Doing This</h3>
<ul>
<li><p><strong>Google</strong> - Invented Kubernetes for this exact purpose</p>
</li>
<li><p><strong>Netflix</strong> - Deploys 1,000+ times daily with confidence</p>
</li>
<li><p><strong>Spotify</strong> - Manages 1,000+ services across teams</p>
</li>
<li><p><strong>Uber</strong> - Global deployments in minutes</p>
</li>
<li><p><strong>Amazon</strong> - Deploys every 11.7 seconds on average</p>
</li>
</ul>
<p>This isn't experimental. This is proven at massive scale.</p>
<hr />
<h2 id="heading-final-thoughts-why-this-project-matters">💭 Final Thoughts: Why This Project Matters</h2>
<p>I started this project to learn. I finished it understanding why Fortune 500 companies invest millions in DevOps.</p>
<p><strong>It's not about the technology.</strong> Kubernetes, ArgoCD, GitHub Actions—these are just tools.</p>
<p><strong>It's about the capability.</strong> The ability to:</p>
<ul>
<li><p>Deploy safely, any time</p>
</li>
<li><p>Scale without manual work</p>
</li>
<li><p>Recover from failures automatically</p>
</li>
<li><p>Move fast without breaking things</p>
</li>
<li><p>Free developers to create instead of deploy</p>
</li>
</ul>
<p>In a world where software is eating everything, deployment velocity is competitive advantage.</p>
<p>Companies that can deploy 100 times per day will outpace companies that deploy 3 times per week. It's that simple.</p>
<p>This project taught me not just HOW modern companies deploy, but WHY they invest so heavily in automation.</p>
<p>And now, so can you.</p>
<hr />
<h2 id="heading-resources-amp-next-steps">🔗 Resources &amp; Next Steps</h2>
<h3 id="heading-want-to-build-this-yourself">Want to Build This Yourself?</h3>
<p><strong>GitHub Repository:</strong> [<a target="_blank" href="https://github.com/saadkhan024">https://github.com/saadkhan024</a>]<br />Complete code, manifests, and setup instructions</p>
<h3 id="heading-continue-learning">Continue Learning</h3>
<p><strong>Official Documentation:</strong></p>
<ul>
<li><p><a target="_blank" href="https://argo-cd.readthedocs.io/">ArgoCD Docs</a></p>
</li>
<li><p><a target="_blank" href="https://kubernetes.io/docs/">Kubernetes Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://opengitops.dev/">GitOps Principles</a></p>
</li>
<li><p><a target="_blank" href="https://aws.github.io/aws-eks-best-practices/">AWS EKS Best Practices</a></p>
</li>
</ul>
<p><strong>Community:</strong></p>
<ul>
<li><p><a target="_blank" href="https://argoproj.github.io/community/join-slack/">ArgoCD Slack</a></p>
</li>
<li><p><a target="_blank" href="https://slack.k8s.io/">Kubernetes Slack</a></p>
</li>
<li><p><a target="_blank" href="https://www.cncf.io/community/">CNCF Community</a></p>
</li>
</ul>
<h3 id="heading-connect-with-me">Connect With Me</h3>
<p>I'm always happy to discuss DevOps, cloud architecture, and automation:</p>
<p><strong>LinkedIn:</strong> [<a target="_blank" href="https://www.linkedin.com/in/saadkhan04/">https://www.linkedin.com/in/saadkhan04/</a>]<br /><strong>GitHub:</strong> [<a target="_blank" href="https://github.com/saadkhan024">https://github.com/saadkhan024</a>]<br /><strong>Twitter:</strong> [<a target="_blank" href="https://x.com/shaadkhan">https://x.com/<em>shaadkhan</em></a>]</p>
<p>If you found this helpful, please share it with someone learning DevOps!</p>
<hr />
<h2 id="heading-lets-discuss">💬 Let's Discuss</h2>
<p><strong>Questions I'd love to hear your thoughts on:</strong></p>
<ul>
<li><p>What's your biggest deployment challenge?</p>
</li>
<li><p>Have you tried GitOps? What was your experience?</p>
</li>
<li><p>What would you build on top of this foundation?</p>
</li>
</ul>
<p>Drop a comment below! I read and respond to all of them.</p>
<hr />
<p><strong>Thanks for reading!</strong> If this article helped you, please:</p>
<ul>
<li><p>👏 Give it some claps (50 is the max!)</p>
</li>
<li><p>💬 Leave a comment with your thoughts</p>
</li>
<li><p>🔄 Share with your network</p>
</li>
<li><p>⭐ Star the GitHub repo</p>
</li>
</ul>
<p><em>Building production infrastructure is complex, but it doesn't have to be complicated. With the right architecture and tools, modern deployment can be elegant, reliable, and even enjoyable.</em></p>
<p><em>Happy deploying! 🚀</em></p>
<hr />
<p><strong>Tags:</strong> #DevOps #GitOps #Kubernetes #CICD #CloudNative #AWS #ArgoCD #Automation #SoftwareEngineering #CloudComputing #InfrastructureAsCode #Microservices #ContainerOrchestration #SRE #PlatformEngineering</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[VIM Essentials: Think of It Like Working in the Cloud.]]></title><description><![CDATA[When most people open VIM for the first time, the reaction is almost universal:
“Why is this so confusing?”
I felt the same—until I changed how I thought about it.
VIM isn’t a typical text editor. It’s closer to cloud architecture than a traditional ...]]></description><link>https://blog.saadkhan.co.in/vim-essentials-think-of-it-like-working-in-the-cloud</link><guid isPermaLink="true">https://blog.saadkhan.co.in/vim-essentials-think-of-it-like-working-in-the-cloud</guid><category><![CDATA[Linux]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Devops]]></category><category><![CDATA[vim]]></category><category><![CDATA[vim linux]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Script]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Sat, 17 Jan 2026 03:56:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768622112057/d9e39383-7237-4546-8583-eb23f3033c7e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When most people open VIM for the first time, the reaction is almost universal:</p>
<p><em>“Why is this so confusing?”</em></p>
<p>I felt the same—until I changed how I thought about it.</p>
<p>VIM isn’t a typical text editor. It’s closer to <strong>cloud architecture</strong> than a traditional GUI tool. Once you understand that VIM is built around <strong>modes, context, and intent</strong>, not mouse clicks, everything starts to make sense.</p>
<h2 id="heading-a-mental-model-that-works">A Mental Model That Works</h2>
<h3 id="heading-normal-mode-control-plane">Normal Mode = Control Plane</h3>
<p>This is where decisions happen. You navigate, inspect, and decide <strong>what</strong> to do next.<br />Most of VIM’s power comes from staying in Normal mode as much as possible.</p>
<h3 id="heading-insert-mode-data-plane">Insert Mode = Data Plane</h3>
<p>This mode exists for one job only: typing.<br />Enter, make the change, and exit quickly. Living here defeats the purpose of VIM.</p>
<h3 id="heading-visual-mode-selection-layer">Visual Mode = Selection Layer</h3>
<p>When you need precision—selecting lines, blocks, or patterns—Visual mode gives you control before taking action.</p>
<h3 id="heading-movement-is-the-foundation">Movement Is the Foundation</h3>
<p>Keys like <code>hjkl</code>, <code>gg</code>, and <code>G</code> are not shortcuts; they’re core design principles.<br />Once movement becomes muscle memory, editing becomes faster than thinking.</p>
<h3 id="heading-saving-and-quitting-matter">Saving and Quitting Matter</h3>
<p>Commands like <code>:w</code>, <code>:q</code>, and <code>:wq</code> may seem basic, but anyone who has worked on production systems knows that <strong>exiting safely</strong> is a real skill.</p>
<hr />
<h2 id="heading-why-vim-still-matters">Why VIM Still Matters</h2>
<p>VIM continues to be relevant because it works where modern tools often don’t:</p>
<ul>
<li><p>Available on almost every server by default</p>
</li>
<li><p>No dependency on a graphical interface</p>
</li>
<li><p>Ideal for cloud, Linux, and remote environments</p>
</li>
<li><p>Exceptional for editing logs, configs, and code over SSH</p>
</li>
</ul>
<hr />
<h2 id="heading-final-thought">Final Thought</h2>
<p>VIM isn’t hard—it’s just different.</p>
<p>Once you respect its modes and stop fighting its design, it becomes one of the most efficient tools in your workflow. Like cloud systems, mastery comes from understanding <strong>how the pieces fit together</strong>, not from memorizing commands.</p>
<p>If you work in Linux or the cloud, learning VIM isn’t optional—it’s leverage.</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[How to Configure a Local YUM Repository: The Interview Question Every Linux Admin Should Know]]></title><description><![CDATA[If you're preparing for a Linux Administrator interview, here's a question you'll likely hear: "How do you patch Linux servers without internet access?" This is one of the most common interview questions, and for good reason – it's a real-world scena...]]></description><link>https://blog.saadkhan.co.in/how-to-configure-a-local-yum-repository-the-interview-question-every-linux-admin-should-know</link><guid isPermaLink="true">https://blog.saadkhan.co.in/how-to-configure-a-local-yum-repository-the-interview-question-every-linux-admin-should-know</guid><category><![CDATA[Linux]]></category><category><![CDATA[linux for beginners]]></category><category><![CDATA[Devops]]></category><category><![CDATA[repository]]></category><category><![CDATA[package manager]]></category><category><![CDATA[linux-commands]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Wed, 31 Dec 2025 08:56:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767171246793/8eb50543-8f3b-4eee-9f45-3b2ca28c1d88.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you're preparing for a Linux Administrator interview, here's a question you'll likely hear: <strong>"How do you patch Linux servers without internet access?"</strong> This is one of the most common interview questions, and for good reason – it's a real-world scenario that many organizations face.</p>
<p>In this guide, I'll walk you through setting up a local YUM repository step-by-step, explain why it matters, and give you the exact answers interviewers are looking for.</p>
<h2 id="heading-why-this-question-appears-in-almost-every-linux-admin-interview">Why This Question Appears in Almost Every Linux Admin Interview</h2>
<p><strong>The Reality:</strong></p>
<ul>
<li><p>Many production servers are in isolated networks (no internet access for security)</p>
</li>
<li><p>Government and financial institutions require air-gapped systems</p>
</li>
<li><p>Data centers often have restricted internet connectivity</p>
</li>
<li><p>Bandwidth limitations make online updates impractical</p>
</li>
</ul>
<p><strong>What Interviewers Want to Know:</strong></p>
<ul>
<li><p>Do you understand enterprise Linux environments?</p>
</li>
<li><p>Can you solve real production problems?</p>
</li>
<li><p>Do you know package management beyond basic <code>yum install</code>?</p>
</li>
<li><p>Can you work in secure, isolated environments?</p>
</li>
</ul>
<p><strong>Pro Interview Tip:</strong> Don't just say "I'll create a local repo." Explain WHY you need it, WHEN you'd use it, and the benefits it provides. This shows deeper understanding.</p>
<h2 id="heading-what-is-a-local-yum-repository">What is a Local YUM Repository?</h2>
<p>Think of it like having your own app store on your phone, but for Linux packages. Instead of downloading from the internet every time, you:</p>
<ol>
<li><p>Download all packages once (from a machine with internet)</p>
</li>
<li><p>Store them locally on your network</p>
</li>
<li><p>Point your servers to this local storage</p>
</li>
<li><p>Servers install/update from your local storage (no internet needed!)</p>
</li>
</ol>
<p><strong>Benefits:</strong></p>
<ul>
<li><p>✅ Patch servers without internet access</p>
</li>
<li><p>✅ Faster updates (local network speed)</p>
</li>
<li><p>✅ Consistent package versions across all servers</p>
</li>
<li><p>✅ Control over what gets installed</p>
</li>
<li><p>✅ Reduced bandwidth usage</p>
</li>
<li><p>✅ Works during internet outages</p>
</li>
</ul>
<h2 id="heading-interview-answer-framework">Interview Answer Framework</h2>
<p>When asked this question in an interview, structure your answer like this:</p>
<p><strong>"I would configure a local YUM repository using the following approach:</strong></p>
<p><strong>1. First, I'd set up a repository server</strong> (a machine with enough storage and network access)</p>
<p><strong>2. Then, I'd copy the packages</strong> either from installation media or by mirroring an online repository</p>
<p><strong>3. Next, I'd create the repository metadata</strong> using the createrepo command</p>
<p><strong>4. Finally, I'd configure client servers</strong> to point to this local repository instead of internet sources</p>
<p><strong>5. For security, I'd also mention</strong> setting up authentication if needed and regular sync schedules."</p>
<p>Now let me show you how to actually do each step!</p>
<h2 id="heading-method-1-using-isodvd-media-quickest-method">Method 1: Using ISO/DVD Media (Quickest Method)</h2>
<p>This is the simplest approach and perfect for air-gapped environments.</p>
<h3 id="heading-step-1-mount-the-iso-file">Step 1: Mount the ISO File</h3>
<p>First, get your RHEL/CentOS/Rocky Linux ISO and mount it:</p>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create a mount point</span>
sudo mkdir -p /mnt/rhel-iso

<span class="hljs-comment"># Mount the ISO file</span>
sudo mount -o loop /path/to/rhel-8.iso /mnt/rhel-iso

<span class="hljs-comment"># Verify it's mounted</span>
ls -lh /mnt/rhel-iso
</code></pre>
<p><strong>Interview Tip:</strong> Mention that the <code>-o loop</code> option lets you mount an ISO file as if it were a physical disk.</p>
<h3 id="heading-step-2-copy-packages-to-a-permanent-location">Step 2: Copy Packages to a Permanent Location</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create directory for your local repository</span>
sudo mkdir -p /var/local-repo/rhel8

<span class="hljs-comment"># Copy all packages from ISO</span>
sudo cp -r /mnt/rhel-iso/* /var/local-repo/rhel8/

<span class="hljs-comment"># Verify packages were copied</span>
ls -lh /var/local-repo/rhel8/BaseOS/Packages/ | head
</code></pre>
<p><strong>Why copy instead of using the mount directly?</strong></p>
<ul>
<li><p>ISO mount is temporary and disappears on reboot</p>
</li>
<li><p>Permanent location allows you to add more packages later</p>
</li>
<li><p>Easier to manage and backup</p>
</li>
</ul>
<h3 id="heading-step-3-create-repository-metadata">Step 3: Create Repository Metadata</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install createrepo tool (do this on a machine with internet, or from ISO)</span>
sudo yum install -y createrepo

<span class="hljs-comment"># Create repository metadata for BaseOS</span>
sudo createrepo /var/local-repo/rhel8/BaseOS/

<span class="hljs-comment"># Create repository metadata for AppStream (if available)</span>
sudo createrepo /var/local-repo/rhel8/AppStream/
</code></pre>
<p><strong>What does createrepo do?</strong></p>
<ul>
<li><p>Creates XML metadata files that YUM uses to find packages</p>
</li>
<li><p>Indexes all RPM files in the directory</p>
</li>
<li><p>Required for YUM to recognize this as a valid repository</p>
</li>
</ul>
<p><strong>Interview Question Follow-up:</strong> "What if I add new packages later?"</p>
<p><strong>Answer:</strong> "I would run <code>createrepo --update /path/to/repo</code> to refresh the metadata without rebuilding everything from scratch."</p>
<h3 id="heading-step-4-create-yum-configuration-file">Step 4: Create YUM Configuration File</h3>
<p>Create a repo file on your server:</p>
<p>bash</p>
<pre><code class="lang-bash">sudo vi /etc/yum.repos.d/local-rhel8.repo
</code></pre>
<p>Add this configuration:</p>
<p>ini</p>
<pre><code class="lang-ini"><span class="hljs-section">[local-base]</span>
<span class="hljs-attr">name</span>=Local RHEL <span class="hljs-number">8</span> BaseOS Repository
<span class="hljs-attr">baseurl</span>=file:///var/local-repo/rhel8/BaseOS
<span class="hljs-attr">enabled</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgcheck</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgkey</span>=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

<span class="hljs-section">[local-appstream]</span>
<span class="hljs-attr">name</span>=Local RHEL <span class="hljs-number">8</span> AppStream Repository
<span class="hljs-attr">baseurl</span>=file:///var/local-repo/rhel8/AppStream
<span class="hljs-attr">enabled</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgcheck</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgkey</span>=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
</code></pre>
<p><strong>Understanding Each Line:</strong></p>
<ul>
<li><p><code>[local-base]</code> = Repository ID (unique name)</p>
</li>
<li><p><code>name=</code> = Human-readable description</p>
</li>
<li><p><code>baseurl=</code> = Location of packages (<a target="_blank">file://</a> for local, http:// for network)</p>
</li>
<li><p><code>enabled=1</code> = Repository is active (0 = disabled)</p>
</li>
<li><p><code>gpgcheck=1</code> = Verify package signatures (security!)</p>
</li>
<li><p><code>gpgkey=</code> = Location of GPG key for verification</p>
</li>
</ul>
<h3 id="heading-step-5-disable-internet-repositories">Step 5: Disable Internet Repositories</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Disable all default repositories</span>
sudo yum-config-manager --<span class="hljs-built_in">disable</span> \*

<span class="hljs-comment"># Or manually disable them</span>
sudo vi /etc/yum.repos.d/redhat.repo
<span class="hljs-comment"># Change enabled=1 to enabled=0 for each repository</span>

<span class="hljs-comment"># Verify only your local repo is enabled</span>
yum repolist
</code></pre>
<p><strong>Expected Output:</strong></p>
<pre><code class="lang-bash">repo id                    repo name
local-base                 Local RHEL 8 BaseOS Repository
local-appstream            Local RHEL 8 AppStream Repository
</code></pre>
<h3 id="heading-step-6-test-your-repository">Step 6: Test Your Repository</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Clean YUM cache</span>
sudo yum clean all

<span class="hljs-comment"># List available packages</span>
yum list available | head -20

<span class="hljs-comment"># Try installing a package</span>
sudo yum install -y vim

<span class="hljs-comment"># Check for updates</span>
sudo yum check-update
</code></pre>
<p><strong>If it works:</strong> ✅ You've successfully configured your local repository!</p>
<p><strong>If it doesn't work:</strong> Check these common issues:</p>
<ul>
<li><p>Is the path correct in the .repo file?</p>
</li>
<li><p>Did you run createrepo?</p>
</li>
<li><p>Are the permissions correct? (chmod 755 on directories)</p>
</li>
<li><p>Is SELinux blocking access? (check with <code>ausearch -m avc</code>)</p>
</li>
</ul>
<h2 id="heading-method-2-network-based-repository-httpftp">Method 2: Network-Based Repository (HTTP/FTP)</h2>
<p>This is the enterprise approach when multiple servers need access.</p>
<h3 id="heading-step-1-set-up-the-repository-server">Step 1: Set Up the Repository Server</h3>
<p>On one server that will host the repository:</p>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install HTTP server</span>
sudo yum install -y httpd

<span class="hljs-comment"># Start and enable Apache</span>
sudo systemctl start httpd
sudo systemctl <span class="hljs-built_in">enable</span> httpd

<span class="hljs-comment"># Open firewall</span>
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
</code></pre>
<h3 id="heading-step-2-copy-packages-to-web-directory">Step 2: Copy Packages to Web Directory</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create repository directory</span>
sudo mkdir -p /var/www/html/repos/rhel8

<span class="hljs-comment"># Copy packages (from ISO or downloaded mirror)</span>
sudo cp -r /mnt/rhel-iso/* /var/www/html/repos/rhel8/

<span class="hljs-comment"># Set proper permissions</span>
sudo chmod -R 755 /var/www/html/repos/
</code></pre>
<h3 id="heading-step-3-create-repository-metadata-1">Step 3: Create Repository Metadata</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install createrepo</span>
sudo yum install -y createrepo

<span class="hljs-comment"># Create metadata</span>
sudo createrepo /var/www/html/repos/rhel8/BaseOS/
sudo createrepo /var/www/html/repos/rhel8/AppStream/
</code></pre>
<h3 id="heading-step-4-configure-client-servers">Step 4: Configure Client Servers</h3>
<p>On each client server, create this repo file:</p>
<p>bash</p>
<pre><code class="lang-bash">sudo vi /etc/yum.repos.d/local-network.repo
</code></pre>
<p>ini</p>
<pre><code class="lang-ini"><span class="hljs-section">[network-base]</span>
<span class="hljs-attr">name</span>=Network RHEL <span class="hljs-number">8</span> BaseOS Repository
<span class="hljs-attr">baseurl</span>=http://repo-server.example.com/repos/rhel8/BaseOS
<span class="hljs-attr">enabled</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgcheck</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgkey</span>=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

<span class="hljs-section">[network-appstream]</span>
<span class="hljs-attr">name</span>=Network RHEL <span class="hljs-number">8</span> AppStream Repository
<span class="hljs-attr">baseurl</span>=http://repo-server.example.com/repos/rhel8/AppStream
<span class="hljs-attr">enabled</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgcheck</span>=<span class="hljs-number">1</span>
<span class="hljs-attr">gpgkey</span>=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
</code></pre>
<p><strong>Replace:</strong> <a target="_blank" href="http://repo-server.example.com"><code>repo-server.example.com</code></a> with your actual server hostname or IP address.</p>
<h3 id="heading-step-5-test-from-client">Step 5: Test from Client</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Clean cache</span>
sudo yum clean all

<span class="hljs-comment"># Test connection to repository</span>
curl http://repo-server.example.com/repos/rhel8/BaseOS/

<span class="hljs-comment"># List repositories</span>
yum repolist

<span class="hljs-comment"># Install a test package</span>
sudo yum install -y wget
</code></pre>
<h2 id="heading-method-3-mirroring-online-repositories-advanced">Method 3: Mirroring Online Repositories (Advanced)</h2>
<p>For environments that need regular updates but have limited internet access.</p>
<h3 id="heading-step-1-install-reposync-tool">Step 1: Install Reposync Tool</h3>
<p>bash</p>
<pre><code class="lang-bash">sudo yum install -y yum-utils createrepo
</code></pre>
<h3 id="heading-step-2-mirror-a-repository">Step 2: Mirror a Repository</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create directory</span>
sudo mkdir -p /var/local-repo/mirror/rhel8

<span class="hljs-comment"># Sync BaseOS repository</span>
sudo reposync \
  --repoid=rhel-8-for-x86_64-baseos-rpms \
  --download-metadata \
  --download-path=/var/local-repo/mirror/rhel8/

<span class="hljs-comment"># Sync AppStream repository</span>
sudo reposync \
  --repoid=rhel-8-for-x86_64-appstream-rpms \
  --download-metadata \
  --download-path=/var/local-repo/mirror/rhel8/
</code></pre>
<p><strong>This will download:</strong></p>
<ul>
<li><p>All packages from the specified repository</p>
</li>
<li><p>Metadata files</p>
</li>
<li><p>Can take time depending on your internet speed</p>
</li>
</ul>
<h3 id="heading-step-3-createupdate-metadata">Step 3: Create/Update Metadata</h3>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create repository metadata</span>
sudo createrepo /var/local-repo/mirror/rhel8/rhel-8-for-x86_64-baseos-rpms/
sudo createrepo /var/local-repo/mirror/rhel8/rhel-8-for-x86_64-appstream-rpms/
</code></pre>
<h3 id="heading-step-4-automate-regular-syncs">Step 4: Automate Regular Syncs</h3>
<p>Create a sync script:</p>
<p>bash</p>
<pre><code class="lang-bash">sudo vi /usr/<span class="hljs-built_in">local</span>/bin/repo-sync.sh
</code></pre>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">"🔄 Starting repository sync..."</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Time: <span class="hljs-subst">$(date)</span>"</span>

<span class="hljs-comment"># Sync repositories</span>
reposync \
  --repoid=rhel-8-for-x86_64-baseos-rpms \
  --download-metadata \
  --newest-only \
  --download-path=/var/local-repo/mirror/rhel8/

reposync \
  --repoid=rhel-8-for-x86_64-appstream-rpms \
  --download-metadata \
  --newest-only \
  --download-path=/var/local-repo/mirror/rhel8/

<span class="hljs-comment"># Update metadata</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"📦 Updating repository metadata..."</span>
createrepo --update /var/local-repo/mirror/rhel8/rhel-8-for-x86_64-baseos-rpms/
createrepo --update /var/local-repo/mirror/rhel8/rhel-8-for-x86_64-appstream-rpms/

<span class="hljs-built_in">echo</span> <span class="hljs-string">"✅ Sync completed!"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"=================================="</span>
</code></pre>
<p>Make it executable:</p>
<p>bash</p>
<pre><code class="lang-bash">sudo chmod +x /usr/<span class="hljs-built_in">local</span>/bin/repo-sync.sh
</code></pre>
<p>Schedule with cron (weekly sync):</p>
<p>bash</p>
<pre><code class="lang-bash">sudo crontab -e
</code></pre>
<p>Add this line:</p>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Sync repository every Sunday at 2 AM</span>
0 2 * * 0 /usr/<span class="hljs-built_in">local</span>/bin/repo-sync.sh &gt;&gt; /var/<span class="hljs-built_in">log</span>/repo-sync.log 2&gt;&amp;1
</code></pre>
<h2 id="heading-interview-deep-dive-questions-amp-answers">Interview Deep-Dive Questions &amp; Answers</h2>
<p>Here are follow-up questions interviewers often ask:</p>
<h3 id="heading-q1-how-do-you-handle-gpg-keys-for-package-verification">Q1: "How do you handle GPG keys for package verification?"</h3>
<p><strong>Answer:</strong></p>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Import GPG key</span>
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

<span class="hljs-comment"># Or from a file</span>
sudo rpm --import /path/to/RPM-GPG-KEY

<span class="hljs-comment"># Verify it's imported</span>
rpm -qa gpg-pubkey*

<span class="hljs-comment"># For custom repositories, you might disable gpgcheck temporarily</span>
<span class="hljs-comment"># but I would NOT recommend this in production due to security risks</span>
</code></pre>
<h3 id="heading-q2-what-if-you-need-to-add-custom-rpms-to-your-repository">Q2: "What if you need to add custom RPMs to your repository?"</h3>
<p><strong>Answer:</strong></p>
<p>bash</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Copy your custom RPM to the repository directory</span>
sudo cp my-custom-app.rpm /var/local-repo/rhel8/BaseOS/Packages/

<span class="hljs-comment"># Update repository metadata</span>
sudo createrepo --update /var/local-repo/rhel8/BaseOS/

<span class="hljs-comment"># Clear client cache</span>
sudo yum clean all

<span class="hljs-comment"># Now the package is available</span>
yum list my-custom-app
</code></pre>
<h3 id="heading-q3-how-would-you-troubleshoot-if-a-client-cant-access-the-repository">Q3: "How would you troubleshoot if a client can't access the repository?"</h3>
<p><strong>Answer:</strong> "I would follow this systematic approach:</p>
<ol>
<li><strong>Check network connectivity:</strong></li>
</ol>
<p>bash</p>
<pre><code class="lang-bash">   ping repo-server.example.com
   curl http://repo-server.example.com/repos/
</code></pre>
<ol start="2">
<li><strong>Verify repository configuration:</strong></li>
</ol>
<p>bash</p>
<pre><code class="lang-bash">   yum repolist all
   cat /etc/yum.repos.d/local-network.repo
</code></pre>
<ol start="3">
<li><strong>Check for YUM cache issues:</strong></li>
</ol>
<p>bash</p>
<pre><code class="lang-bash">   sudo yum clean all
   sudo rm -rf /var/cache/yum/*
</code></pre>
<ol start="4">
<li><strong>Test with verbose mode:</strong></li>
</ol>
<p>bash</p>
<pre><code class="lang-bash">   yum -v repolist
</code></pre>
<ol start="5">
<li><strong>Check server logs:</strong></li>
</ol>
<p>bash</p>
<pre><code class="lang-bash">   <span class="hljs-comment"># On repository server</span>
   sudo tail -f /var/<span class="hljs-built_in">log</span>/httpd/access_log
   sudo tail -f /var/<span class="hljs-built_in">log</span>/httpd/error_log
</code></pre>
<ol start="6">
<li><strong>Verify SELinux contexts:</strong></li>
</ol>
<p>bash</p>
<pre><code class="lang-bash">   ls -Z /var/www/html/repos/
   sudo restorecon -Rv /var/www/html/repos/
</code></pre>
<ol start="7">
<li><strong>Check firewall rules:</strong></li>
</ol>
<p>bash</p>
<pre><code class="lang-bash">sudo firewall-cmd --list-all
````<span class="hljs-string">"

### Q4: "</span>How <span class="hljs-keyword">do</span> you ensure all servers use the same package versions?<span class="hljs-string">"

**Answer:**
"</span>Several approaches:

1. **Use version locking:**
```bash
   sudo yum install yum-plugin-versionlock
   sudo yum versionlock add package-name
```

2. **Snapshot your repository** at a specific point <span class="hljs-keyword">in</span> time

3. **Use different repositories <span class="hljs-keyword">for</span> different environments:**
   - `/repos/dev/` - development packages
   - `/repos/staging/` - tested packages
   - `/repos/prod/` - approved production packages

4. **Implement a change control process** before updating the repository<span class="hljs-string">"

### Q5: "</span>What are the security considerations?<span class="hljs-string">"

**Answer:**
"</span>Key security considerations:

1. **Enable GPG checking** - Always verify package signatures
2. **Use HTTPS instead of HTTP** <span class="hljs-keyword">if</span> possible <span class="hljs-keyword">for</span> network repos
3. **Implement authentication** - Apache basic auth or certificate-based
4. **Restrict access** - Firewall rules to allow only specific servers
5. **Regular audits** - Monitor what packages are being installed
6. **Secure the repository server** - Harden it like any production server
7. **Control who can add packages** - Limit write access to the repository<span class="hljs-string">"

## Common Mistakes to Avoid

### ❌ Mistake 1: Not Running createrepo
```bash
# This won't work - no metadata!
sudo cp *.rpm /var/local-repo/

# Do this instead:
sudo cp *.rpm /var/local-repo/
sudo createrepo /var/local-repo/
```

### ❌ Mistake 2: Wrong Permissions
```bash
# Files aren't readable
sudo chmod 600 /var/www/html/repos/*  # Wrong!

# Make them readable
sudo chmod -R 755 /var/www/html/repos/  # Correct!
```

### ❌ Mistake 3: Forgetting to Update Metadata
```bash
# Add new packages
sudo cp new-package.rpm /var/local-repo/

# Forgot this! YUM won't see the new package
sudo createrepo --update /var/local-repo/
```

### ❌ Mistake 4: Not Testing Before Production
Always test your repository setup on a non-critical server first!

### ❌ Mistake 5: Mixing RHEL Versions
Don't mix RHEL 7, 8, and 9 packages in the same repository. Create separate repos for each version.

## Real-World Scenario: Complete Setup

Let me walk you through a realistic enterprise scenario:

**Scenario:** You have 50 RHEL 8 servers in a secure data center with no internet access. You need to patch them monthly.

**Solution:**

### Repository Server Setup (One-time)
```bash
# 1. Set up repository server (has temporary internet access)
sudo yum install -y httpd createrepo yum-utils

# 2. Create directory structure
sudo mkdir -p /var/www/html/repos/rhel8/{BaseOS,AppStream}

# 3. Sync from Red Hat (while internet is available)
sudo reposync \
  --repoid=rhel-8-for-x86_64-baseos-rpms \
  --download-metadata \
  --download-path=/var/www/html/repos/rhel8/BaseOS/

sudo reposync \
  --repoid=rhel-8-for-x86_64-appstream-rpms \
  --download-metadata \
  --download-path=/var/www/html/repos/rhel8/AppStream/

# 4. Create metadata
sudo createrepo /var/www/html/repos/rhel8/BaseOS/
sudo createrepo /var/www/html/repos/rhel8/AppStream/

# 5. Set permissions
sudo chmod -R 755 /var/www/html/repos/

# 6. Start Apache
sudo systemctl start httpd
sudo systemctl enable httpd

# 7. Configure firewall
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
```

### Client Configuration (All 50 servers)

Use Ansible or a script to deploy this to all servers:
```bash
# Create repository configuration
cat &gt; /etc/yum.repos.d/internal-rhel8.repo &lt;&lt; 'EOF'
[internal-base]
name=Internal RHEL 8 BaseOS
baseurl=http://10.0.1.100/repos/rhel8/BaseOS
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

[internal-appstream]
name=Internal RHEL 8 AppStream
baseurl=http://10.0.1.100/repos/rhel8/AppStream
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
EOF

# Disable external repositories
yum-config-manager --disable \*

# Enable only internal repositories
yum-config-manager --enable internal-base internal-appstream

# Test
yum clean all
yum repolist
```

### Monthly Patching Process
```bash
# 1. On repository server (connect to internet temporarily)
sudo /usr/local/bin/repo-sync.sh

# 2. Test updates on one server
sudo yum check-update
sudo yum update -y

# 3. If successful, update remaining servers in batches
# Use Ansible, parallel-ssh, or a rolling update script
```

## Advanced: Automating with Ansible

Create an Ansible playbook for repository configuration:
```yaml
---
- name: Configure Local YUM Repository
  hosts: all_servers
  become: yes

  tasks:
    - name: Create repository configuration
      copy:
        dest: /etc/yum.repos.d/internal-rhel8.repo
        content: |
          [internal-base]
          name=Internal RHEL 8 BaseOS
          baseurl=http://{{ repo_server }}/repos/rhel8/BaseOS
          enabled=1
          gpgcheck=1
          gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

          [internal-appstream]
          name=Internal RHEL 8 AppStream
          baseurl=http://{{ repo_server }}/repos/rhel8/AppStream
          enabled=1
          gpgcheck=1
          gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

    - name: Disable external repositories
      shell: yum-config-manager --disable \*

    - name: Enable internal repositories
      shell: yum-config-manager --enable internal-base internal-appstream

    - name: Clean YUM cache
      command: yum clean all

    - name: Verify repository access
      command: yum repolist
      register: repo_output

    - name: Display repositories
      debug:
        var: repo_output.stdout_lines
```

Run it:
```bash
ansible-playbook -i inventory configure-repos.yml -e "</span>repo_server=10.0.1.100<span class="hljs-string">"
```

## Monitoring and Maintenance

### Check Repository Health

Create a monitoring script:
```bash
#!/bin/bash

echo "</span>Repository Health Check<span class="hljs-string">"
echo "</span>=======================<span class="hljs-string">"
echo "</span>Date: $(date)<span class="hljs-string">"
echo "</span><span class="hljs-string">"

# Check disk space
echo "</span>📊 Disk Space:<span class="hljs-string">"
df -h /var/www/html/repos/
echo "</span><span class="hljs-string">"

# Count packages
echo "</span>📦 Package Count:<span class="hljs-string">"
echo "</span>BaseOS: $(find /var/www/html/repos/rhel8/BaseOS -name <span class="hljs-string">"*.rpm"</span> | wc -l)<span class="hljs-string">"
echo "</span>AppStream: $(find /var/www/html/repos/rhel8/AppStream -name <span class="hljs-string">"*.rpm"</span> | wc -l)<span class="hljs-string">"
echo "</span><span class="hljs-string">"

# Check Apache status
echo "</span>🌐 Apache Status:<span class="hljs-string">"
systemctl status httpd | grep Active
echo "</span><span class="hljs-string">"

# Check recent access
echo "</span>📈 Recent Access (last 10 requests):<span class="hljs-string">"
tail -10 /var/log/httpd/access_log
echo "</span><span class="hljs-string">"

# Verify metadata integrity
echo "</span>🔍 Metadata Check:<span class="hljs-string">"
if [ -f "</span>/var/www/html/repos/rhel8/BaseOS/repodata/repomd.xml<span class="hljs-string">" ]; then
    echo "</span>✅ BaseOS metadata exists<span class="hljs-string">"
else
    echo "</span>❌ BaseOS metadata missing!<span class="hljs-string">"
fi

if [ -f "</span>/var/www/html/repos/rhel8/AppStream/repodata/repomd.xml<span class="hljs-string">" ]; then
    echo "</span>✅ AppStream metadata exists<span class="hljs-string">"
else
    echo "</span>❌ AppStream metadata missing!<span class="hljs-string">"
fi
```

## Quick Reference Cheat Sheet

### Essential Commands
```bash
# Mount ISO
mount -o loop rhel.iso /mnt/iso

# Create repository metadata
createrepo /path/to/repo

# Update existing metadata
createrepo --update /path/to/repo

# Sync from online repository
reposync --repoid=repo-name --download-path=/path/

# List repositories
yum repolist
yum repolist all

# Clean cache
yum clean all

# Test repository
yum list available

# Check for updates
yum check-update
```

### Repository File Template
```ini
[repo-id]
name=Repository Description
baseurl=http://server/path  # or file:///local/path
enabled=1                    # 1=enabled, 0=disabled
gpgcheck=1                   # 1=verify signatures
gpgkey=file:///path/to/key  # GPG key location
priority=1                   # Lower number = higher priority (with priorities plugin)
```

## Conclusion

Setting up a local YUM repository is an essential skill for Linux administrators, especially in enterprise environments. Whether you're:

- Working in secure, air-gapped networks
- Managing large server fleets
- Preparing for Linux admin interviews
- Looking to optimize your patching process

Understanding local repositories will serve you well.

**Key Takeaways:**

✅ **Three main methods:** ISO-based (simplest), Network-based (enterprise), Mirror-based (hybrid)

✅ **Core steps:** Copy packages → Create metadata → Configure clients → Test

✅ **Interview success:** Explain WHY, not just HOW, and mention security considerations

✅ **Real world:** Combine with automation tools like Ansible for scale

✅ **Maintenance:** Regular syncs, monitoring, and testing are crucial

**Practice Makes Perfect:**

Set up a local repository in a lab environment. Try all three methods. Break it and fix it. This hands-on experience will make you confident when answering this question in interviews or implementing it in production.

Good luck with your interviews! 🚀</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Understanding Linux File Permissions: A Visual Guide]]></title><description><![CDATA[Introduction
Have you ever encountered a "Permission denied" error while trying to access a file on Linux? Or wondered what those cryptic rwxr-xr-- characters mean when you run ls -l? Understanding Linux file permissions is fundamental to working wit...]]></description><link>https://blog.saadkhan.co.in/understanding-linux-file-permissions-a-visual-guide</link><guid isPermaLink="true">https://blog.saadkhan.co.in/understanding-linux-file-permissions-a-visual-guide</guid><category><![CDATA[Linux]]></category><category><![CDATA[linux for beginners]]></category><category><![CDATA[linux-permissions]]></category><category><![CDATA[linux-basics]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Tue, 30 Dec 2025 04:08:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767067626909/711a06f2-cca3-437d-9fe9-d233e008b4a1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Have you ever encountered a "Permission denied" error while trying to access a file on Linux? Or wondered what those cryptic <code>rwxr-xr--</code> characters mean when you run <code>ls -l</code>? Understanding Linux file permissions is fundamental to working with any Unix-like operating system, whether you're a developer, system administrator, or just getting started with Linux.</p>
<p>In this comprehensive visual guide, we'll demystify Linux file permissions, explore how they work, and learn how to manage them effectively. By the end, you'll confidently navigate file ownership, permissions, and security on any Linux system.</p>
<h2 id="heading-what-are-file-permissions">What Are File Permissions?</h2>
<p>File permissions in Linux are a security mechanism that controls who can read, write, or execute files and directories. Every file and directory has an associated set of permissions that determine three levels of access:</p>
<ol>
<li><p><strong>Owner (User)</strong> - The user who owns the file</p>
</li>
<li><p><strong>Group</strong> - Users who are members of the file's group</p>
</li>
<li><p><strong>Others</strong> - Everyone else on the system</p>
</li>
</ol>
<h1 id="heading-for-each-of-these-three-categories-linux-defines-three-types-of-permissions">For each of these three categories, Linux defines three types of permissions:</h1>
<ul>
<li><p><strong>Read (r)</strong> - View the file contents or list directory contents</p>
</li>
<li><p><strong>Write (w)</strong> - Modify the file or directory contents</p>
</li>
<li><p><strong>Execute (x)</strong> - Run the file as a program or access the directory</p>
</li>
</ul>
<p>This combination of three permission types across three user categories creates a powerful and flexible security model.</p>
<h2 id="heading-viewing-file-permissions">Viewing File Permissions</h2>
<p>Let's start by looking at how to view permissions. The <code>ls -l</code> command displays detailed information about files, including their permissions:</p>
<p>bash</p>
<pre><code class="lang-bash">$ ls -l
total 24
-rw-r--r-- 1 alice developers 1024 Dec 15 10:30 document.txt
-rwxr-xr-x 1 alice developers 2048 Dec 15 10:31 script.sh
drwxr-xr-x 2 alice developers 4096 Dec 15 10:32 my_directory
-rw-rw---- 1 alice developers  512 Dec 15 10:33 private.txt
</code></pre>
<p>Let's break down what each part means:</p>
<pre><code class="lang-bash">-rw-r--r-- 1 alice developers 1024 Dec 15 10:30 document.txt
│└┬┘└┬┘└┬┘ │  │     │          │    │            │
│ │  │  │  │  │     │          │    │            └─ Filename
│ │  │  │  │  │     │          │    └─ Modification time
│ │  │  │  │  │     │          └─ File size (bytes)
│ │  │  │  │  │     └─ Group name
│ │  │  │  │  └─ Owner name
│ │  │  │  └─ Number of hard links
│ │  │  └─ Others permissions (<span class="hljs-built_in">read</span>, no write, no execute)
│ │  └─ Group permissions (<span class="hljs-built_in">read</span>, no write, no execute)
│ └─ Owner permissions (<span class="hljs-built_in">read</span>, write, no execute)
└─ File <span class="hljs-built_in">type</span> (- = regular file, d = directory, l = symbolic link)
</code></pre>
<h2 id="heading-the-three-permission-types">The Three Permission Types</h2>
<h3 id="heading-1-read-permission-r">1. Read Permission (r)</h3>
<p><strong>For Files:</strong></p>
<ul>
<li><p>View the file contents</p>
</li>
<li><p>Copy the file</p>
</li>
<li><p>Examples: <code>cat</code>, <code>less</code>, <code>grep</code>, <code>cp</code></p>
</li>
</ul>
<p><strong>For Directories:</strong></p>
<ul>
<li><p>List the directory contents</p>
</li>
<li><p>See filenames inside the directory</p>
</li>
<li><p>Example: <code>ls directory_name</code></p>
</li>
</ul>
<p><strong>Important Note:</strong> Read permission on a directory doesn't grant access to file contents, only to see the names of files in the directory.</p>
<h3 id="heading-2-write-permission-w">2. Write Permission (w)</h3>
<p><strong>For Files:</strong></p>
<ul>
<li><p>Modify file contents</p>
</li>
<li><p>Delete the file (if directory also has write permission)</p>
</li>
<li><p>Rename the file (if directory also has write permission)</p>
</li>
<li><p>Examples: <code>nano</code>, <code>vim</code>, <code>echo</code>, <code>rm</code></p>
</li>
</ul>
<p><strong>For Directories:</strong></p>
<ul>
<li><p>Create new files in the directory</p>
</li>
<li><p>Delete files from the directory</p>
</li>
<li><p>Rename files in the directory</p>
</li>
<li><p>Create subdirectories</p>
</li>
<li><p>Examples: <code>touch</code>, <code>mkdir</code>, <code>rm</code>, <code>mv</code></p>
</li>
</ul>
<p><strong>Important Note:</strong> Write permission on a directory allows you to delete files even if you don't have write permission on the files themselves!</p>
<h3 id="heading-3-execute-permission-x">3. Execute Permission (x)</h3>
<p><strong>For Files:</strong></p>
<ul>
<li><p>Run the file as a program or script</p>
</li>
<li><p>Examples: <code>./</code><a target="_blank" href="http://script.sh"><code>script.sh</code></a>, <code>python</code> <a target="_blank" href="http://program.py"><code>program.py</code></a></p>
</li>
</ul>
<p><strong>For Directories:</strong></p>
<ul>
<li><p>Access (enter) the directory</p>
</li>
<li><p>Access files within the directory if you know their names</p>
</li>
<li><p>Make it the current directory with <code>cd</code></p>
</li>
<li><p>Example: <code>cd directory_name</code></p>
</li>
</ul>
<p><strong>Critical Note:</strong> Without execute permission on a directory, you cannot access ANY files in that directory, even if you have read permission on the directory!</p>
<h2 id="heading-the-three-user-categories">The Three User Categories</h2>
<h3 id="heading-1-owner-user">1. Owner (User)</h3>
<p>The user who owns the file. Usually the person who created it, but ownership can be transferred.</p>
<p><strong>Example:</strong> Alice creates a file, so Alice is the owner.</p>
<h3 id="heading-2-group">2. Group</h3>
<p>A collection of users who share access to files. Every file belongs to one group.</p>
<p><strong>Example:</strong> Alice and Bob are both in the "developers" group, so files owned by this group are accessible to both.</p>
<h3 id="heading-3-others-world">3. Others (World)</h3>
<p>Everyone else on the system who is neither the owner nor in the group.</p>
<p><strong>Example:</strong> Any user on the system who isn't Alice and isn't in the "developers" group.</p>
<h2 id="heading-permission-notation-two-ways">Permission Notation: Two Ways</h2>
<p>Linux represents permissions in two different notations: symbolic (letters) and octal (numbers).</p>
<h3 id="heading-symbolic-notation-rwx">Symbolic Notation (rwx)</h3>
<p>Uses letters to represent permissions:</p>
<ul>
<li><p><code>r</code> = read</p>
</li>
<li><p><code>w</code> = write</p>
</li>
<li><p><code>x</code> = execute</p>
</li>
<li><p><code>-</code> = no permission</p>
</li>
</ul>
<p><strong>Format:</strong> <code>rwxrwxrwx</code></p>
<ul>
<li><p>First three characters = owner permissions</p>
</li>
<li><p>Second three characters = group permissions</p>
</li>
<li><p>Third three characters = others permissions</p>
</li>
</ul>
<p><strong>Examples:</strong></p>
<pre><code class="lang-bash">rwxr-xr-x  Owner: <span class="hljs-built_in">read</span>, write, execute | Group: <span class="hljs-built_in">read</span>, execute | Others: <span class="hljs-built_in">read</span>, execute
rw-r--r--  Owner: <span class="hljs-built_in">read</span>, write | Group: <span class="hljs-built_in">read</span> | Others: <span class="hljs-built_in">read</span>
rwx------  Owner: <span class="hljs-built_in">read</span>, write, execute | Group: none | Others: none
r--------  Owner: <span class="hljs-built_in">read</span> only | Group: none | Others: none
</code></pre>
<h3 id="heading-octal-numeric-notation">Octal (Numeric) Notation</h3>
<p>Uses numbers 0-7 to represent permissions. Each permission has a numeric value:</p>
<ul>
<li><p><code>r</code> (read) = 4</p>
</li>
<li><p><code>w</code> (write) = 2</p>
</li>
<li><p><code>x</code> (execute) = 1</p>
</li>
</ul>
<p>Add these values together to get the permission number for each category.</p>
<p><strong>Common Permission Values:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Octal</td><td>Binary</td><td>Symbolic</td><td>Meaning</td></tr>
</thead>
<tbody>
<tr>
<td>0</td><td>000</td><td>---</td><td>No permissions</td></tr>
<tr>
<td>1</td><td>001</td><td>--x</td><td>Execute only</td></tr>
<tr>
<td>2</td><td>010</td><td>-w-</td><td>Write only</td></tr>
<tr>
<td>3</td><td>011</td><td>-wx</td><td>Write and execute</td></tr>
<tr>
<td>4</td><td>100</td><td>r--</td><td>Read only</td></tr>
<tr>
<td>5</td><td>101</td><td>r-x</td><td>Read and execute</td></tr>
<tr>
<td>6</td><td>110</td><td>rw-</td><td>Read and write</td></tr>
<tr>
<td>7</td><td>111</td><td>rwx</td><td>Read, write, and execute</td></tr>
</tbody>
</table>
</div><p><strong>Example Conversions:</strong></p>
<pre><code class="lang-bash">rwxr-xr-x = 755
- Owner: rwx = 4+2+1 = 7
- Group: r-x = 4+0+1 = 5
- Others: r-x = 4+0+1 = 5

rw-r--r-- = 644
- Owner: rw- = 4+2+0 = 6
- Group: r-- = 4+0+0 = 4
- Others: r-- = 4+0+0 = 4

rwx------ = 700
- Owner: rwx = 4+2+1 = 7
- Group: --- = 0+0+0 = 0
- Others: --- = 0+0+0 = 0
</code></pre>
<h2 id="heading-special-permissions">Special Permissions</h2>
<p>Beyond the basic read, write, and execute permissions, Linux has three special permission bits:</p>
<h3 id="heading-1-setuid-set-user-id-4000">1. Setuid (Set User ID) - 4000</h3>
<p>When set on an executable file, the program runs with the permissions of the file's owner, not the user who executed it.</p>
<h3 id="heading-2-setgid-set-group-id-2000">2. Setgid (Set Group ID) - 2000</h3>
<p><strong>On Files:</strong> Program runs with the group permissions of the file's group.</p>
<p><strong>On Directories:</strong> New files created in the directory inherit the directory's group, not the creator's default group.</p>
<h3 id="heading-3-sticky-bit-1000">3. Sticky Bit - 1000</h3>
<p>When set on a directory, only the file owner, directory owner, or root can delete or rename files in that directory, even if others have write permission.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Understanding Linux file permissions is crucial for anyone working with Linux systems. While the concept might seem complex at first, the logic is straightforward:</p>
<ol>
<li><p><strong>Three permission types</strong>: Read (r), Write (w), Execute (x)</p>
</li>
<li><p><strong>Three user categories</strong>: Owner (u), Group (g), Others (o)</p>
</li>
<li><p><strong>Two notations</strong>: Symbolic (rwx) and Octal (755)</p>
</li>
<li><p><strong>Three commands</strong>: chmod (change permissions), chown (change owner), chgrp (change group)</p>
</li>
</ol>
<p>Mastering file permissions allows you to:</p>
<ul>
<li><p>Secure sensitive data</p>
</li>
<li><p>Set up collaborative workspaces</p>
</li>
<li><p>Troubleshoot access issues</p>
</li>
<li><p>Configure servers correctly</p>
</li>
<li><p>Follow security best practices</p>
</li>
</ul>
<p>Remember the principle of least privilege: start with restrictive permissions and open them up only as needed. When in doubt, use 644 for files and 755 for directories—these are safe defaults that work for most scenarios.</p>
<p>As you continue your Linux journey, file permissions will become second nature. Practice with the examples in this guide, experiment in a safe environment, and don't be afraid to check permissions frequently with <code>ls -l</code>. Happy securing!</p>
<h2 id="heading-further-reading-and-resources">Further Reading and Resources</h2>
<ul>
<li><p><strong>man chmod</strong>: Detailed manual page (<code>man chmod</code>)</p>
</li>
<li><p><strong>man chown</strong>: Ownership manual (<code>man chown</code>)</p>
</li>
<li><p><strong>POSIX Permissions</strong>: Standards documentation</p>
</li>
<li><p><strong>Advanced Topics</strong>: Access Control Lists (ACLs), SELinux contexts</p>
</li>
<li><p><strong>Practice</strong>: Set up a local Linux VM and experiment safely</p>
</li>
</ul>
<p><strong>What permission challenges have you faced? Share your experiences in the comments below!</strong></p>
<p><strong>Tags:</strong> #Linux #FilePermissions #SystemAdministration #Security #DevOps #CommandLine #Tutorial</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[Build Your Own Self-Hosted File Sharing & Backup System on Linux]]></title><description><![CDATA[Learn how to create a personal cloud storage solution with automated backups and a modern web interface using Linux, Python, and Nginx.
Introduction
In today’s world, managing your own data securely is more important than ever. While cloud services a...]]></description><link>https://blog.saadkhan.co.in/build-your-own-self-hosted-file-sharing-and-backup-system-on-linux</link><guid isPermaLink="true">https://blog.saadkhan.co.in/build-your-own-self-hosted-file-sharing-and-backup-system-on-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[Developer]]></category><category><![CDATA[articles]]></category><category><![CDATA[Linux]]></category><category><![CDATA[automation]]></category><category><![CDATA[Backup]]></category><category><![CDATA[server]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Mon, 13 Oct 2025 17:15:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760375605525/c9ed3d0c-3236-4698-b798-52f7bbc0c4c6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-learn-how-to-create-a-personal-cloud-storage-solution-with-automated-backups-and-a-modern-web-interface-using-linux-python-and-nginx">Learn how to create a personal cloud storage solution with automated backups and a modern web interface using Linux, Python, and Nginx.</h2>
<h2 id="heading-introduction">Introduction</h2>
<p>In today’s world, managing your own data securely is more important than ever. While cloud services are convenient, self-hosted solutions give you <strong>full control</strong>, <strong>privacy</strong>, and a chance to showcase your Linux sysadmin and DevOps skills.</p>
<p>In this post, I’ll walk you through building a <strong>Self-Hosted File Sharing &amp; Backup System</strong> that lets you upload, download, and backup files from a web interface—all hosted on your Linux server.</p>
<h2 id="heading-why-build-a-self-hosted-system">Why Build a Self-Hosted System?</h2>
<ul>
<li><p><strong>Privacy &amp; Security:</strong> Your data stays under your control.</p>
</li>
<li><p><strong>Learning Opportunity:</strong> Demonstrates Linux server setup, Nginx, Python web apps, and automation scripts.</p>
</li>
<li><p><strong>Portfolio Value:</strong> Perfect for showing off full-stack Linux + DevOps skills.</p>
</li>
</ul>
<h2 id="heading-tech-stack">Tech Stack</h2>
<ul>
<li><p><strong>Linux server:</strong> CentOS / Ubuntu</p>
</li>
<li><p><strong>Web server:</strong> Nginx</p>
</li>
<li><p><strong>Backend:</strong> Python (Flask)</p>
</li>
<li><p><strong>Automation:</strong> Bash scripts for backups</p>
</li>
<li><p><strong>Web UI:</strong> HTML/CSS/JS (modern, colorful, and responsive)</p>
</li>
<li><p><strong>Optional:</strong> Docker + Nextcloud for scalability</p>
</li>
</ul>
<h2 id="heading-features">Features</h2>
<ul>
<li><p>Upload and download files securely</p>
</li>
<li><p>View uploaded files in a clean, modern interface</p>
</li>
<li><p>Trigger automated backups to a separate folder</p>
</li>
<li><p>View backup logs from the web UI</p>
</li>
<li><p>Easy deployment on any Linux server or VM</p>
</li>
</ul>
<h3 id="heading-step-by-step-setup"><strong>Step-by-Step Setup</strong></h3>
<p>1. Prepare the Server</p>
<p>sudo yum update -y sudo yum install python3 python3-venv python3-pip nginx git -y</p>
<p>2. Clone the Project</p>
<p># git clone &lt;your-repo-url&gt;</p>
<p>#cd file_sharing_system</p>
<p>#python3 -m venv venv</p>
<p>#source venv/bin/activate</p>
<p>#pip install -r requirements.txt</p>
<p>3. Run the App</p>
<p>For development:</p>
<p>#python <a target="_blank" href="http://app.py">app.py</a></p>
<p>For production with Gunicorn + Nginx:</p>
<p>gunicorn --bind 0.0.0.0:8000 app:app</p>
<h3 id="heading-frontend-amp-ui">Frontend &amp; UI</h3>
<p>I designed a <strong>colorful and modern web UI</strong> with responsive buttons and cards for uploaded files. The theme makes it visually appealing and intuitive to use.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760375057358/bc852af7-ae7e-4f19-ad9e-a03fc17a7cbb.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-automating-backups">Automating Backups</h2>
<p>Backups are handled via a <strong>Bash script</strong> (<a target="_blank" href="http://backup.sh"><code>backup.sh</code></a>) that copies files to a backup folder and logs the operation. You can also trigger backups from the web UI.</p>
<h2 id="heading-security-tips">Security Tips</h2>
<ul>
<li><p>Use HTTPS via <strong>Certbot</strong> for Nginx</p>
</li>
<li><p>Set strong file permissions</p>
</li>
<li><p>Keep your server and packages updated</p>
</li>
</ul>
<p><strong>Note: If you want the code please refer my GitHub Repo, it is now private i will make it public. Till then Bye.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Docker Architecture on a Physical Server vs. Virtual Machine Architecture]]></title><description><![CDATA[Traditional Virtualization Architecture with Docker on VMs
Description: In traditional virtualization, multiple virtual machines (VMs) run on a physical server using a hypervisor. Each VM includes a guest OS and can run Docker containers within it.
L...]]></description><link>https://blog.saadkhan.co.in/docker-architecture-on-a-physical-server-vs-virtual-machine-architecture</link><guid isPermaLink="true">https://blog.saadkhan.co.in/docker-architecture-on-a-physical-server-vs-virtual-machine-architecture</guid><category><![CDATA[Docker]]></category><category><![CDATA[docker images]]></category><category><![CDATA[Docker compose]]></category><category><![CDATA[#Dockerfile #DockerImage #Containerization #DevOps #ContainerizationTechnology #DockerBuild #DockerRun #DockerContainer #DockerCompose #DockerHub #ContainerDeployment #CloudNative #ContainerizationBestPractices #DevOpsTools #CI/CD Feel free to select the relevant hashtags based on the specific focus of your blog post.]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Thu, 20 Jun 2024 03:18:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718853486059/29ac1abd-56dc-423f-ac6b-05edea332cd7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h4 id="heading-traditional-virtualization-architecture-with-docker-on-vms">Traditional Virtualization Architecture with Docker on VMs</h4>
<p><strong>Description:</strong> In traditional virtualization, multiple virtual machines (VMs) run on a physical server using a hypervisor. Each VM includes a guest OS and can run Docker containers within it.</p>
<p><strong>Layers Explanation:</strong></p>
<ul>
<li><p><strong>Physical Server:</strong> The actual hardware resources (CPU, memory, storage, etc.).</p>
</li>
<li><p><strong>Hypervisor:</strong> A layer that creates and manages VMs, allowing multiple OS instances to run on a single physical server.</p>
</li>
<li><p><strong>VM (Virtual Machine):</strong> An emulation of a physical computer. Each VM runs its own guest OS.</p>
</li>
<li><p><strong>Guest OS:</strong> The operating system running inside each VM.</p>
</li>
<li><p><strong>Docker Engine:</strong> The Docker daemon running on the guest OS, managing containers.</p>
</li>
<li><p><strong>Containers:</strong> Lightweight and portable execution environments that include everything needed to run a piece of software, except the OS.</p>
</li>
</ul>
<h4 id="heading-docker-architecture-on-a-physical-server">Docker Architecture on a Physical Server</h4>
<p><strong>Description:</strong> Docker containers run directly on the host OS of the physical server, without the need for a hypervisor or VMs. This provides better performance and efficiency.</p>
<p><strong>Layers Explanation:</strong></p>
<ul>
<li><p><strong>Physical Server:</strong> The actual hardware resources (CPU, memory, storage, etc.).</p>
</li>
<li><p><strong>Host OS:</strong> The operating system running directly on the physical server.</p>
</li>
<li><p><strong>Docker Engine:</strong> The Docker daemon running on the host OS, managing containers.</p>
</li>
<li><p><strong>Containers:</strong> Lightweight and portable execution environments that include everything needed to run a piece of software, sharing the host OS kernel, but isolated from each other.</p>
</li>
</ul>
<h3 id="heading-comparison">Comparison:</h3>
<ul>
<li><p><strong>Resource Efficiency:</strong></p>
<ul>
<li>Docker containers on a physical server share the host OS kernel, making them more lightweight and efficient compared to VMs which each have their own OS.</li>
</ul>
</li>
<li><p><strong>Performance:</strong></p>
<ul>
<li>Containers typically have better performance compared to VMs because there's no hypervisor overhead and they utilize fewer resources since they share the host OS kernel.</li>
</ul>
</li>
<li><p><strong>Isolation:</strong></p>
<ul>
<li><p>VMs provide stronger isolation as each VM includes its own OS, which can be an advantage for certain security requirements.</p>
</li>
<li><p>Containers provide isolation at the process level, which is generally sufficient for most applications but not as strong as VM isolation.</p>
</li>
</ul>
</li>
<li><p><strong>Boot Time:</strong></p>
<ul>
<li>Containers start much faster than VMs because they do not require a full OS boot.</li>
</ul>
</li>
</ul>
<h3 id="heading-learning-resources-for-docker">Learning Resources for Docker:</h3>
<ol>
<li><p><strong>Official Documentation:</strong></p>
<ul>
<li>Docker Docs: https://docs.docker.com/</li>
</ul>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Working with Git Hooks: An Introduction]]></title><description><![CDATA[Git hooks are scripts that Git executes before or after certain events such as committing, pushing, or receiving changes. They are a powerful way to automate tasks and enforce policies in your Git workflow. This guide will introduce you to Git hooks ...]]></description><link>https://blog.saadkhan.co.in/working-with-git-hooks-an-introduction</link><guid isPermaLink="true">https://blog.saadkhan.co.in/working-with-git-hooks-an-introduction</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[GitLab]]></category><category><![CDATA[github-actions]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Sun, 16 Jun 2024 14:17:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718366422718/e479b907-1489-4f3f-a144-32473d0d8498.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Git hooks are scripts that Git executes before or after certain events such as committing, pushing, or receiving changes. They are a powerful way to automate tasks and enforce policies in your Git workflow. This guide will introduce you to Git hooks and show you how to use them effectively.</p>
<h3 id="heading-what-are-git-hooks">What Are Git Hooks?</h3>
<p>Git hooks are custom scripts that run automatically when certain Git events occur. They can be used for a variety of purposes, such as:</p>
<ul>
<li><p>Enforcing code quality standards</p>
</li>
<li><p>Running tests before allowing a commit</p>
</li>
<li><p>Sending notifications</p>
</li>
<li><p>Formatting code</p>
</li>
<li><p>Automating deployments</p>
</li>
</ul>
<h3 id="heading-types-of-git-hooks">Types of Git Hooks</h3>
<p>Git hooks are categorized into client-side and server-side hooks:</p>
<ol>
<li><p><strong>Client-Side Hooks</strong>: These hooks run on your local machine and are typically used to automate tasks related to commits, merges, and other local operations.</p>
<ul>
<li><p><strong>Pre-Commit Hook</strong>: Runs before a commit is created. It’s commonly used to check the code quality or run tests.</p>
</li>
<li><p><strong>Prepare-Commit-Message Hook</strong>: Runs before the commit message editor is fired up. It’s used to prepare the default commit message.</p>
</li>
<li><p><strong>Commit-Message Hook</strong>: Runs after the commit message is created but before the commit is finalized. It’s used to verify or modify the commit message.</p>
</li>
<li><p><strong>Post-Commit Hook</strong>: Runs after a commit is made. It’s often used for notifications or to perform follow-up actions like pushing the commit.</p>
</li>
<li><p><strong>Pre-Push Hook</strong>: Runs before any push to a remote repository. It’s used to validate changes before they are pushed.</p>
</li>
</ul>
</li>
<li><p><strong>Server-Side Hooks</strong>: These hooks run on the remote repository server and are used to enforce policies or perform actions when changes are pushed to the repository.</p>
<ul>
<li><p><strong>Pre-Receive Hook</strong>: Runs before any changes are accepted by the remote repository. It can be used to enforce policies.</p>
</li>
<li><p><strong>Update Hook</strong>: Runs after the pre-receive hook but before the changes are applied. It’s used to enforce branch-specific policies.</p>
</li>
<li><p><strong>Post-Receive Hook</strong>: Runs after the changes are accepted. It’s used for notifications and deployments.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-how-to-set-up-git-hooks">How to Set Up Git Hooks</h3>
<p>    Git hooks are stored in the <code>.git/hooks</code> directory of your repository. By default, this directory contains sample scripts that can be modified to suit your needs.</p>
<ol>
<li><p><strong>Locate the Hooks Directory</strong>:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> your-repo/.git/hooks
</code></pre>
</li>
<li><p><strong>Create or Modify a Hook Script</strong>: Hooks are shell scripts (or any executable file). To create a pre-commit hook, for example:</p>
<pre><code class="lang-bash"> touch pre-commit
 chmod +x pre-commit
</code></pre>
</li>
<li><p><strong>Edit the Hook Script</strong>: Open <code>pre-commit</code> in your favorite text editor and add your custom logic. For example, to prevent commits with messages containing "WIP":</p>
<pre><code class="lang-bash"> <span class="hljs-comment">#!/bin/sh</span>
 <span class="hljs-keyword">if</span> git <span class="hljs-built_in">log</span> -1 | grep -q <span class="hljs-string">"WIP"</span>; <span class="hljs-keyword">then</span>
   <span class="hljs-built_in">echo</span> <span class="hljs-string">"Aborting commit: Work in Progress (WIP) commits are not allowed."</span>
   <span class="hljs-built_in">exit</span> 1
 <span class="hljs-keyword">fi</span>
</code></pre>
</li>
</ol>
<h3 id="heading-example-pre-commit-hook-to-run-tests">Example: Pre-Commit Hook to Run Tests</h3>
<p>    Here's an example of a <code>pre-commit</code> hook that runs tests before allowing a commit:</p>
<pre><code class="lang-bash">    <span class="hljs-comment">#!/bin/sh</span>
    <span class="hljs-comment"># Run tests before committing</span>
    npm <span class="hljs-built_in">test</span>
    <span class="hljs-keyword">if</span> [ $? -ne 0 ]; <span class="hljs-keyword">then</span>
      <span class="hljs-built_in">echo</span> <span class="hljs-string">"Tests failed, commit aborted."</span>
      <span class="hljs-built_in">exit</span> 1
    <span class="hljs-keyword">fi</span>
</code></pre>
<h3 id="heading-example-post-commit-hook-to-notify-team">Example: Post-Commit Hook to Notify Team</h3>
<p>    Here's an example of a <code>post-commit</code> hook that sends a notification after a commit:</p>
<pre><code class="lang-bash">    <span class="hljs-comment">#!/bin/sh</span>
    <span class="hljs-comment"># Send a notification after committing</span>
    commit_message=$(git <span class="hljs-built_in">log</span> -1 --pretty=format:%s)
    curl -X POST -H <span class="hljs-string">'Content-type: application/json'</span> \
    --data <span class="hljs-string">'{"text":"New commit: '</span><span class="hljs-string">"<span class="hljs-variable">$commit_message</span>"</span><span class="hljs-string">'"}'</span> \
    https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
</code></pre>
<h3 id="heading-best-practices-for-using-git-hooks">Best Practices for Using Git Hooks</h3>
<ul>
<li><p><strong>Keep Hooks Simple</strong>: Hooks should be straightforward and quick to run to avoid slowing down your workflow.</p>
</li>
<li><p><strong>Make Hooks Shareable</strong>: Store your hooks in a version-controlled directory and create symlinks in <code>.git/hooks</code> to share them with your team.</p>
</li>
<li><p><strong>Use a Hook Manager</strong>: Consider using tools like <a target="_blank" href="https://github.com/typicode/husky">Husky</a> for JavaScript projects or <a target="_blank" href="https://pre-commit.com/">pre-commit</a> for Python projects to manage hooks more easily.</p>
</li>
</ul>
<p>    Here's a visual representation of where Git hooks fit into the Git workflow:</p>
<pre><code class="lang-bash">        Client-Side Hooks
           (Local Repository)
      ----------------------------------
      | Pre-Commit | Commit-Message   |
      | Prepare-Commit-Message        |
      | Post-Commit  | Pre-Push       |
      ----------------------------------

                 |
                 V

          Server-Side Hooks
           (Remote Repository)
      ----------------------------------
      | Pre-Receive  | Update          |
      | Post-Receive                   |
      ----------------------------------
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>    Git hooks are a powerful tool to automate and enforce policies in your Git workflow. By understanding and utilizing hooks, you can significantly enhance your development process, ensuring higher code quality and smoother operations. Start by setting up basic hooks, and gradually integrate more complex automation as needed.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Git Rebase: An Alternative to Merging]]></title><description><![CDATA[When learning Git, programmers typically start with commands like add, commit, push, pull, status, branch, checkout, and merge. After mastering these foundational commands, it's important to understand the rebase command.
Rebasing is often used as an...]]></description><link>https://blog.saadkhan.co.in/understanding-git-rebase-an-alternative-to-merging</link><guid isPermaLink="true">https://blog.saadkhan.co.in/understanding-git-rebase-an-alternative-to-merging</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[git rebase]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Fri, 14 Jun 2024 09:51:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718358664982/de284903-49b6-4947-b9b8-8a03d63fbffd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When learning Git, programmers typically start with commands like <code>add</code>, <code>commit</code>, <code>push</code>, <code>pull</code>, <code>status</code>, <code>branch</code>, <code>checkout</code>, and <code>merge</code>. After mastering these foundational commands, it's important to understand the <code>rebase</code> command.</p>
<p>Rebasing is often used as an alternative to merging. It updates one branch with the commits of another by applying the commits of one branch on top of the other. For example, if you're working on a feature branch that is out of date with a dev branch, you can rebase the feature branch onto dev to include all the new commits from dev. Here's a visual representation of this process:</p>
<p><strong>Before Rebase</strong></p>
<pre><code class="lang-bash">dev:     A---B---C---D
              \
feature:        E---F---G
</code></pre>
<h4 id="heading-after-rebase">After Rebase</h4>
<pre><code class="lang-bash">dev:     A---B---C---D
                    \
feature:             E<span class="hljs-string">'---F'</span>---G<span class="hljs-string">'</span>
</code></pre>
<p>In command line, you can achieve this with:</p>
<pre><code class="lang-bash">git rebase dev feature
</code></pre>
<p>However, the more common approach is:</p>
<pre><code class="lang-bash">git checkout feature
git rebase dev
</code></pre>
<h3 id="heading-typical-rebase-use-cases">Typical Rebase Use Cases</h3>
<h4 id="heading-updating-a-feature-branch">Updating a Feature Branch</h4>
<p>Imagine you're working on a feature branch, diligently adding commits.</p>
<pre><code class="lang-bash">feature:  E---F---G
</code></pre>
<p>Then you notice new commits on the dev branch that may impact your feature branch.</p>
<pre><code class="lang-bash">dev:     A---B---C---D
feature:  E---F---G
</code></pre>
<p>You decide to run <code>git rebase dev</code> from your feature branch to get up-to-date with dev.</p>
<pre><code class="lang-bash">git checkout feature
git rebase dev
</code></pre>
<p>During the rebase, conflicts may arise between your changes and the new commits on dev. Git will notify you of conflicts and the files that need resolution. After resolving conflicts, you add the changes with <code>git add</code> and continue the rebase process with <code>git rebase --continue</code>. If there are no more conflicts, your feature branch will be successfully rebased onto dev.</p>
<pre><code class="lang-bash">dev:     A---B---C---D
                    \
feature:             E<span class="hljs-string">'---F'</span>---G<span class="hljs-string">'</span>
</code></pre>
<p>Now, your feature branch includes the latest commits from dev, and you can continue working seamlessly.</p>
<h4 id="heading-updating-a-feature-branch-prior-to-merge">Updating a Feature Branch Prior to Merge</h4>
<p>Another common use for rebasing is to update a feature branch before merging it into the dev branch. Initially, the state of your branches might look like this:</p>
<pre><code class="lang-bash">dev:     A---B---C
              \
feature:        D---E
</code></pre>
<p>Once your feature is complete, you should rebase it onto dev before merging:</p>
<pre><code class="lang-bash">git checkout feature
git rebase dev
</code></pre>
<pre><code class="lang-bash">dev:     A---B---C
                    \
feature:             D<span class="hljs-string">'---E'</span>
</code></pre>
<p>Next, merge your feature branch into dev. This is often done through a Pull Request for review. The result will be:</p>
<pre><code class="lang-bash">dev:     A---B---C---D<span class="hljs-string">'---E'</span>
</code></pre>
<p>Rebasing before merging ensures that all commits from the feature branch appear at the end of the dev branch. This happens because rebasing rewrites commit history, giving new hashes and timestamps to the commits. Consequently, when you merge a rebased feature branch into dev, all the feature branch commits are ordered chronologically at the end.</p>
<h3 id="heading-summary">Summary</h3>
<p>Understanding how to rebase is essential for efficient Git workflows. Whether updating a feature branch with the latest changes from dev or preparing a branch for merging, <code>rebase</code> ensures a clean and organized commit history.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Cherry-Picking in Git]]></title><description><![CDATA[As developers, we frequently use version control systems like Git to manage our codebase. One feature in Git that can be both powerful and potentially problematic if misused is cherry-picking.
What is Cherry-Picking in Git?
Cherry-picking is a featur...]]></description><link>https://blog.saadkhan.co.in/understanding-cherry-picking-in-git</link><guid isPermaLink="true">https://blog.saadkhan.co.in/understanding-cherry-picking-in-git</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[cherry-pick]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Thu, 13 Jun 2024 20:21:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718309952270/5b8d1b7a-895b-414e-a979-6d7d90bd755e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As developers, we frequently use version control systems like Git to manage our codebase. One feature in Git that can be both powerful and potentially problematic if misused is <strong>cherry-picking</strong>.</p>
<h2 id="heading-what-is-cherry-picking-in-git">What is Cherry-Picking in Git?</h2>
<p>Cherry-picking is a feature that allows you to apply a specific commit from one branch into another. This can be incredibly useful for applying bug fixes or features without merging an entire branch. However, it should be used with caution.</p>
<h2 id="heading-when-to-use-cherry-picking">When to Use Cherry-Picking</h2>
<ol>
<li><p><strong>Bug Fixes</strong>: If you need to apply a critical bug fix from one branch to another without merging all the changes.</p>
</li>
<li><p><strong>Selective Features</strong>: When you want to include a specific feature or change without integrating all branch changes.</p>
</li>
</ol>
<h3 id="heading-cherry-picking-command">Cherry-Picking Command</h3>
<p>To cherry-pick a commit, you can use the following command:</p>
<p><strong>git cherry-pick</strong></p>
<p>Replace <code>&lt;commit-hash&gt;</code> with the hash of the commit you want to cherry-pick. For example:</p>
<p><strong>git cherry-pick a1b2c3d4</strong></p>
<h2 id="heading-potential-issues-with-cherry-picking">Potential Issues with Cherry-Picking</h2>
<ol>
<li><p><strong>Merge Conflicts</strong>: Cherry-picking can lead to merge conflicts if the changes are not compatible.</p>
</li>
<li><p><strong>History Divergence</strong>: Overusing cherry-picking can lead to a fragmented history, making it harder to track changes.</p>
</li>
<li><p><strong>Inconsistencies</strong>: If not managed carefully, it can result in inconsistencies between branches.</p>
</li>
</ol>
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p><strong>Use Sparingly</strong>: Only cherry-pick when necessary and ensure it's the best solution for your use case.</p>
</li>
<li><p><strong>Document Your Changes</strong>: Clearly document the reason for cherry-picking in your commit messages.</p>
</li>
<li><p><strong>Follow-Up with Merges</strong>: Plan to merge the branches eventually to keep the history clean and consistent.</p>
</li>
</ol>
<h3 id="heading-merge-command">Merge Command</h3>
<p>To merge a branch, you can use the following command:</p>
<pre><code class="lang-basic">git <span class="hljs-keyword">merge</span> &lt;branch-<span class="hljs-keyword">name</span>&gt;
</code></pre>
<p>For example, to merge a <code>feature-branch</code> into the <code>main</code> branch:</p>
<pre><code class="lang-basic">git checkout main
git <span class="hljs-keyword">merge</span> feature-branch
</code></pre>
<h2 id="heading-diagram-cherry-picking-vs-merging-in-git">Diagram: Cherry-Picking vs. Merging in Git</h2>
<p>To visually represent cherry-picking in Git, you can create a diagram that shows the difference between cherry-picking a commit and merging branches.</p>
<h3 id="heading-diagram-title-cherry-picking-vs-merging-in-git">Diagram Title: Cherry-Picking vs. Merging in Git</h3>
<h3 id="heading-two-scenarios">Two Scenarios:</h3>
<p><strong>Left Scenario (Cherry-Picking):</strong></p>
<ul>
<li><p>Show two branches: <code>feature-branch</code> and <code>main</code>.</p>
</li>
<li><p>Highlight a single commit from <code>feature-branch</code> being applied to <code>main</code>.</p>
</li>
<li><p>Indicate potential issues like conflicts and fragmented history.</p>
</li>
</ul>
<p><strong>Right Scenario (Merging):</strong></p>
<ul>
<li><p>Show the same two branches.</p>
</li>
<li><p>Illustrate a full merge from <code>feature-branch</code> to <code>main</code>.</p>
</li>
<li><p>Highlight the clean and consistent history resulting from the merge.</p>
</li>
</ul>
<h3 id="heading-key-labels-and-annotations">Key Labels and Annotations:</h3>
<ul>
<li><p>Highlight the selective nature on the left side with annotations like "Selective Commit" and "Potential Conflicts".</p>
</li>
<li><p>Highlight the thorough approach on the right side with annotations like "Full Merge" and "Consistent History".</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718309752854/d626aa4a-f15d-4a40-aecb-56df5bdb0b84.png" alt class="image--center mx-auto" /></p>
<p>++++++++++++++++++++++++<strong>Thank You</strong>++++++++++++++++++++++++++++</p>
]]></content:encoded></item><item><title><![CDATA[Day 3| Azure Zero to Hero: Unveiling the Power of Resources and Resource Groups]]></title><description><![CDATA[Welcome back to Day 3 of our exhilarating Azure Zero to Hero journey! Today, we're delving into the fundamental elements that shape the Azure landscape: Resources, Resource Groups, and the orchestration wizard—Azure Resource Manager (ARM). But before...]]></description><link>https://blog.saadkhan.co.in/day-3-azure-zero-to-hero-unveiling-the-power-of-resources-and-resource-groups</link><guid isPermaLink="true">https://blog.saadkhan.co.in/day-3-azure-zero-to-hero-unveiling-the-power-of-resources-and-resource-groups</guid><category><![CDATA[resource group]]></category><category><![CDATA[Azure]]></category><category><![CDATA[resources]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Fri, 26 Jan 2024 13:38:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706276154363/cf724efd-01c5-4f5a-b4a8-439cd9e3b330.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome back to Day 3 of our exhilarating Azure Zero to Hero journey! Today, we're delving into the fundamental elements that shape the Azure landscape: <strong>Resources</strong>, <strong>Resource Groups</strong>, and the orchestration wizard—<strong>Azure Resource Manager (ARM)</strong>. But before we dive into the intricacies, a heartfelt thank you to Abhishek Veeramalla for crafting an invaluable resource that serves as our guiding light in this Azure adventure!</p>
<h2 id="heading-understanding-resources-in-azure"><strong>Understanding Resources in Azure.</strong></h2>
<p>In the vast expanse of Azure, a resource is anything you might need to create or manage—an Azure Virtual Machine, a storage account, a database, and beyond. They are the bricks that build the digital edifice of our applications and services.</p>
<h2 id="heading-unveiling-the-magic-of-resource-groups"><strong>Unveiling the Magic of Resource Groups.</strong></h2>
<p>Enter the Azure Resource Group, the virtuoso organizer of our Azure symphony. Think of it as a digital container that not only holds your resources but also streamlines management, enhances security, and simplifies billing. It's your go-to tool for staying organized and efficient in the ever-expanding Azure universe.</p>
<h2 id="heading-azure-resource-manager-the-maestro-of-orchestration"><strong>Azure Resource Manager: The Maestro of Orchestration.</strong></h2>
<p>ARM takes center stage, orchestrating the deployment and management of resources. With ARM, we can define and deploy our infrastructure as code, bringing scalability, consistency, and repeatability to our projects. It transforms the complex task of resource management into a harmonious and scalable process.</p>
<h2 id="heading-real-time-use-cases-bringing-concepts-to-life"><strong>Real-Time Use-Cases: Bringing Concepts to Life.</strong></h2>
<p>Let's step into the real world where Resource Groups become the unsung heroes of cloud infrastructure. From deploying scalable web applications to managing intricate data pipelines, Resource Groups offer clarity, simplicity, and efficiency. They are the backbone of Azure, ensuring updates are seamless, and security is robust.</p>
<h2 id="heading-embracing-industry-best-practices"><strong>Embracing Industry Best Practices</strong></h2>
<p>Resource Groups are not just features; they're best practices. In the Azure ecosystem, effective utilization of Resource Groups ensures operational efficiency, cost-effectiveness, and compliance adherence. They're the cornerstone of industry-grade cloud solutions, providing a structured approach to cloud architecture.</p>
<p>As we wrap up Day 3, let's carry this newfound knowledge into the next leg of our Azure adventure. Stay tuned for more insights, challenges, and triumphs as we navigate the Azure landscape together!</p>
]]></content:encoded></item><item><title><![CDATA[Day-2 | Azure (Zero-to-Hero) | A Beginner's Guide to Azure: Account Creation, Regions, and Service Models.]]></title><description><![CDATA[Introduction:
Embarking on the cloud journey can be a game-changer for businesses and individuals alike. Microsoft Azure, a leading cloud computing platform, offers a plethora of services. In this blog, we'll walk you through the essential steps to k...]]></description><link>https://blog.saadkhan.co.in/day-2-azure-zero-to-hero-a-beginners-guide-to-azure-account-creation-regions-and-service-models</link><guid isPermaLink="true">https://blog.saadkhan.co.in/day-2-azure-zero-to-hero-a-beginners-guide-to-azure-account-creation-regions-and-service-models</guid><category><![CDATA[Azure]]></category><category><![CDATA[IaaS]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[PaaS]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Thu, 25 Jan 2024 08:33:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706171006857/de7d1183-d5c1-42a1-b900-d05131f5c553.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction"><strong>Introduction:</strong></h1>
<p>Embarking on the cloud journey can be a game-changer for businesses and individuals alike. Microsoft Azure, a leading cloud computing platform, offers a plethora of services. In this blog, we'll walk you through the essential steps to kickstart your Azure experience - from creating an account to understanding regions, availability zones, and the different service models.</p>
<h3 id="heading-creating-an-account-with-azure"><strong>Creating an Account with Azure</strong></h3>
<p><strong>Step 1: Visit the Azure Portal</strong></p>
<p><a target="_blank" href="https://portal.azure.com/">Navigate to</a> the <a target="_blank" href="https://portal.azure.com/">Azure Portal</a>, a<a target="_blank" href="https://portal.azure.com/">nd click on</a> "Start free" if you're a new user. Existing users can log in with their credentials.</p>
<p><strong>Step 2: Account Setup</strong></p>
<p>Follow t<a target="_blank" href="https://portal.azure.com/">he on-screen</a> instructio<a target="_blank" href="https://portal.azure.com/">ns to set up</a> your Azure account. This involves providing some basic information, choosing a subscription plan, and adding payment details if needed.</p>
<p><strong>Step 3: Activate Your Subscript</strong><a target="_blank" href="https://portal.azure.com/"><strong>ion</strong></a></p>
<p><a target="_blank" href="https://portal.azure.com/">Once yo</a>ur account is set up, ac<a target="_blank" href="https://portal.azure.com/">tivate your</a> subscription. Azure often provides free trial credits, allowing you to explore various services without incurring immediate charges.</p>
<h3 id="heading-exploring-regions-and-availability-zones-in-azure"><strong>Exploring Regions and Availability Zones in Azure.</strong></h3>
<p><strong>Understanding Regions:</strong></p>
<p>Azure is a global platform with data centers distributed across the world. These data centers are grouped into regions. A region is a geographical area containing at least one data center that houses Azure resources. When selecting a region, consider factors like latency, data residency, and service availability.</p>
<p><strong>Navigating Availability Zones:</strong></p>
<p>Regions are further divided into Availability Zones, each comprising one or more data centers. Availability Zones enhance fault tolerance by ensuring that your applications remain operational even if one zone faces issues. It's crucial to deploy resources across multiple zones for high availability.</p>
<p><strong>Choosing the Right Region and Availability Zone:</strong></p>
<p>Selecting the optimal region and availability zone depends on your specific requirements. Consider the location of your users, regulatory compliance, and the redundancy needed for your applications.</p>
<p><strong><br />Title: A Beginner's Guide to Azure: Account Creation, Regions, and Service Models</strong></p>
<hr />
<p><strong>Introduction:</strong></p>
<p>Embarking on the cloud journey can be a game-changer for businesses and individuals alike. Microsoft Azure, a leading cloud computing platform, offers a plethora of services. In this blog, we'll walk you through the essential steps to kickstart your Azure experience - from creating an account to understanding regions, availability zones, and the different service models.</p>
<hr />
<h3 id="heading-creating-an-account-with-azure-1"><strong>Creating an Account with Azure</strong></h3>
<p><strong>Step 1: Visit the Azure Portal</strong></p>
<p>Navigate to the <a target="_blank" href="https://portal.azure.com/">Azure Portal</a>, and click on "Start free" if you're a new user. Existing users can log in with their credentials.</p>
<p><strong>Step 2: Account Setup</strong></p>
<p>Follow the on-screen instructions to set up your Azure account. This involves providing some basic information, choosing a subscription plan, and adding payment details if needed.</p>
<p><strong>Step 3: Activate Your Subscription</strong></p>
<p>Once your account is set up, activate your subscription. Azure often provides free trial credits, allowing you to explore various services without incurring immediate charges.</p>
<hr />
<h3 id="heading-exploring-regions-and-availability-zones-in-azure-1"><strong>Exploring Regions and Availability Zones in Azure</strong></h3>
<p><strong>Understanding Regions:</strong></p>
<p>Azure is a global platform with data centers distributed across the world. These data centers are grouped into regions. A region is a geographical area containing at least one data center that houses Azure resources. When selecting a region, consider factors like latency, data residency, and service availability.</p>
<p><strong>Navigating Availability Zones:</strong></p>
<p>Regions are further divided into Availability Zones, each comprising one or more data centers. Availability Zones enhance fault tolerance by ensuring that your applications remain operational even if one zone faces issues. It's crucial to deploy resources across multiple zones for high availability.</p>
<p><strong>Choosing the Right Region and Availability Zone:</strong></p>
<p>Selecting the optimal region and availability zone depends on your specific requirements. Consider the location of your users, regulatory compliance, and the redundancy needed for your applications.</p>
<hr />
<h3 id="heading-iaas-vs-paas-vs-saas-models-in-azure"><strong>IaaS vs PaaS vs SaaS Models in Azure</strong></h3>
<p><strong>Infrastructure as a Service (IaaS):</strong></p>
<p>IaaS provides virtualized computing resources over the internet. Azure's IaaS offerings include virtual machines, storage, and networking. This model is suitable for those who need control over the operating system and applications.</p>
<p><strong>Platform as a Service (PaaS):</strong></p>
<p>PaaS abstracts away the underlying infrastructure, allowing developers to focus on building and deploying applications. Azure App Service, Azure Functions, and Azure SQL Database are examples of PaaS offerings. It's an excellent choice for developers who want to streamline the development process.</p>
<p><strong>Software as a Service (SaaS):</strong></p>
<p>SaaS delivers software applications over the internet on a subscription basis. In Azure, examples of SaaS include Office 365 and Dynamics 365. SaaS is ideal for users who want ready-to-use applications without the hassle of managing infrastructure.</p>
<p><strong>Conclusion:</strong></p>
<p>By now, you've laid the foundation for your Azure journey. Whether you're an individual looking to enhance your skills or a business aiming for digital transformation, understanding account creation, regions, availability zones, and service models is crucial. Stay tuned for more insights into Azure's vast ecosystem and unlock the full potential of cloud computing. Happy cloud exploring!</p>
]]></content:encoded></item><item><title><![CDATA[Day-1 | Azure  (Zero-to-Hero) | Starting with Azure.]]></title><description><![CDATA[Basics of Cloud Computing:
What is Cloud ?
In simpler terms, imagine the cloud as a vast, virtual space where you can store files, run software, and access various services over the internet.
It's like having a powerful computer somewhere out there o...]]></description><link>https://blog.saadkhan.co.in/day-0-azure-zero-to-hero-starting-with-azure</link><guid isPermaLink="true">https://blog.saadkhan.co.in/day-0-azure-zero-to-hero-starting-with-azure</guid><category><![CDATA[Azure]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Cloud Computing]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Sun, 21 Jan 2024 07:29:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705822623382/941983ed-9f29-44f9-8ffb-f5e0a373e36d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-basics-of-cloud-computing">Basics of Cloud Computing:</h1>
<h2 id="heading-what-is-cloud">What is Cloud ?</h2>
<p>In simpler terms, imagine the cloud as a vast, virtual space where you can store files, run software, and access various services over the internet.</p>
<p>It's like having a powerful computer somewhere out there on the web that you can use for tasks without needing to own or physically manage the hardware. This allows users to access data and applications from anywhere with an internet connection.</p>
<h2 id="heading-what-is-cloud-computing">What is Cloud Computing ?</h2>
<p>Cloud computing is a technology model that involves the delivery of computing services over the internet. Instead of owning and maintaining physical servers and infrastructure, users can access and use computing resources, applications, and storage provided by either third-party service providers (public cloud) or their own organization (private cloud) through the internet. These services are hosted in data centers located around the world.</p>
<p>In essence, cloud computing can involve both third-party providers (public cloud) and an organization's internal resources (private cloud). The distinction lies in whether the computing resources are shared among multiple customers (public cloud) or dedicated to a single organization (private cloud). The flexibility of cloud computing allows organizations to choose the deployment model that best aligns with their needs and requirements.</p>
<h2 id="heading-public-cloud">Public Cloud:</h2>
<p>Azure Public Cloud is a comprehensive cloud computing platform provided by Microsoft, offering a wide array of on-demand services accessible over the internet. Users can leverage Azure's extensive infrastructure to deploy virtual machines, storage, databases, and various other resources without the need for investing in and maintaining physical hardware. Azure's public cloud model allows for scalability, flexibility, and cost-effectiveness, catering to diverse business needs on a pay-as-you-go basis. It is an ideal solution for organizations seeking rapid deployment and global accessibility of their applications and services.</p>
<h2 id="heading-private-cloud">Private Cloud:</h2>
<p>Azure supports the creation and management of Private Clouds, allowing organizations to establish dedicated cloud environments tailored to their specific requirements. Whether hosted on-premises or by a third-party service provider, Azure's Private Cloud solutions provide enhanced control, security, and customization. Organizations can leverage Azure's tools and services to build and manage their private cloud infrastructure, ensuring a reliable and scalable environment while retaining the benefits of cloud computing. This is particularly advantageous for businesses with stringent security and compliance needs.</p>
<h2 id="heading-hybrid-cloud">Hybrid Cloud:</h2>
<p>Azure Hybrid Cloud seamlessly integrates on-premises data centers with Azure's public cloud, offering a flexible and efficient solution for businesses with diverse IT requirements. Azure's Hybrid Cloud services, such as Azure Arc, enable organizations to extend their on-premises infrastructure to the cloud, ensuring a consistent and unified management experience across both environments. This approach allows for the seamless migration of workloads, data, and applications between on-premises and the cloud, optimizing resource utilization, scalability, and cost-effectiveness. Azure's Hybrid Cloud is a strategic choice for organizations seeking a balance between the benefits of public and private cloud models.</p>
<h1 id="heading-vocabulary-in-cloud-computing">Vocabulary in Cloud Computing</h1>
<p>1.Virtualization</p>
<p>2. Virtual Machine</p>
<p>3.API (Application Programming Interface)</p>
<p>4.Regions</p>
<p>5.Availability Zones</p>
<p>6.Scalability</p>
<p>7.Elasticity</p>
<p>8.Agility</p>
<p>9.High Availability</p>
<p>10.Fault Tolerance</p>
<p>11.Disaster Recovery</p>
<p>12.Load Balancing</p>
<h1 id="heading-virtualization">Virtualization:</h1>
<p>Virtualization in Azure refers to the process of creating a virtual representation of physical resources, such as servers, storage, or networks. This technology allows multiple virtual instances to run on a single physical machine, optimizing resource utilization and improving overall efficiency.</p>
<h1 id="heading-virtual-machine"><strong>Virtual Machine:</strong></h1>
<p>Azure Virtual Machines (VMs) are on-demand, scalable computing resources that run applications. These virtualized instances provide flexibility in terms of operating systems, storage, and networking configurations, allowing users to tailor their computing environment to specific needs.</p>
<h1 id="heading-api-application-programming-interface"><strong>API (Application Programming Interface):</strong></h1>
<p>APIs in Azure provide a set of protocols and tools for building software applications. They allow different software components to communicate and enable developers to integrate Azure services into their applications, facilitating seamless interactions with cloud resources.</p>
<h1 id="heading-regions"><strong>Regions:</strong></h1>
<p>Azure divides its global infrastructure into regions, which are geographical areas containing one or more data centers. Each region is designed to be independent of others, providing redundancy and ensuring data sovereignty for users by allowing them to choose where their data resides.</p>
<h1 id="heading-availability-zones"><strong>Availability Zones:</strong></h1>
<p>Availability Zones in Azure are physically separate data centers within a region. These zones are designed to provide high availability by distributing resources across multiple locations, helping to ensure that applications and data remain accessible even in the face of localized failures.</p>
<h1 id="heading-scalability"><strong>Scalability:</strong></h1>
<p>Azure offers scalability, allowing users to adjust their resources based on demand. This can involve scaling up to handle increased workload or scaling down during periods of lower demand, providing cost efficiency and performance optimization.</p>
<h1 id="heading-elasticity"><strong>Elasticity:</strong></h1>
<p>Elasticity in Azure refers to the automatic scaling of resources based on demand. It allows systems to dynamically adapt to changing workloads by automatically provisioning or de-provisioning resources, ensuring optimal performance and cost-effectiveness.</p>
<h1 id="heading-agility"><strong>Agility:</strong></h1>
<p>Azure's agility is the ability to quickly and easily deploy, manage, and scale applications. This flexibility allows developers and businesses to adapt to changing requirements, experiment with new ideas, and respond swiftly to market changes.</p>
<h1 id="heading-high-availability"><strong>High Availability:</strong></h1>
<p>High Availability in Azure ensures that applications and services are continuously operational and accessible. This is achieved through redundancy, failover mechanisms, and load balancing, minimizing downtime and providing a reliable user experience.</p>
<h1 id="heading-fault-tolerance"><strong>Fault Tolerance:</strong></h1>
<p>Fault Tolerance in Azure involves designing systems to withstand and recover from hardware or software failures. By implementing redundant components and failover mechanisms, Azure enhances the resilience of applications, minimizing the impact of faults.</p>
<h1 id="heading-disaster-recovery"><strong>Disaster Recovery:</strong></h1>
<p>Azure's Disaster Recovery solutions enable businesses to plan for and recover from disruptive events. By replicating data and applications to a secondary location, organizations can ensure business continuity in the event of a disaster, minimizing data loss and downtime.</p>
<h1 id="heading-load-balancing"><strong>Load Balancing:</strong></h1>
<p>Load balancing in Azure distributes incoming network traffic across multiple servers to ensure optimal resource utilization and prevent overload on any single server. This enhances the availability and reliability of applications by efficiently managing traffic distribution.</p>
]]></content:encoded></item><item><title><![CDATA[Exploring Amazon S3 Operations with Python Boto3 SDK]]></title><description><![CDATA[Amazon Simple Storage Service (S3) is a powerful and scalable object storage service offered by Amazon Web Services (AWS). It allows developers to store and retrieve any amount of data at any time. To interact with S3 programmatically, AWS provides t...]]></description><link>https://blog.saadkhan.co.in/exploring-amazon-s3-operations-with-python-boto3-sdk</link><guid isPermaLink="true">https://blog.saadkhan.co.in/exploring-amazon-s3-operations-with-python-boto3-sdk</guid><category><![CDATA[AWS]]></category><category><![CDATA[S3]]></category><category><![CDATA[S3-bucket]]></category><category><![CDATA[Python]]></category><category><![CDATA[boto3]]></category><category><![CDATA[aws cli]]></category><category><![CDATA[sdk]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Fri, 19 Jan 2024 16:29:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705614552600/44e288f4-8087-493e-99ab-fba198c787ab.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Amazon Simple Storage Service (S3) is a powerful and scalable object storage service offered by Amazon Web Services (AWS). It allows developers to store and retrieve any amount of data at any time. To interact with S3 programmatically, AWS provides the Boto3 SDK for Python, which simplifies the process of integrating your applications with S3.</p>
<p>In this blog post, we'll explore the basic operations you can perform with S3 using the Boto3 SDK. We'll cover creating an S3 bucket, deleting a bucket, uploading a file to a bucket, and downloading a file from a bucket.</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before diving into the code, make sure you have the following prerequisites:</p>
<ol>
<li><p><strong>AWS Account:</strong> You need an AWS account with appropriate permissions to create and manage S3 resources.</p>
</li>
<li><p><strong>AWS Access Key and Secret Key:</strong> Obtain your AWS access key and secret key from the AWS Management Console.</p>
</li>
<li><p><strong>Boto3 Installation:</strong> Install the Boto3 library using the following command:</p>
</li>
</ol>
<p><mark>pip install boto3</mark></p>
<h2 id="heading-setting-up-boto3"><strong>Setting Up Boto3</strong></h2>
<p>To start using Boto3, you need to configure your AWS credentials. Create a new Python script and configure Boto3 with your AWS credentials or You can configure the AWS CLI with below given details.</p>
<p>Configuring the AWS Command Line Interface (CLI) is a crucial step for interacting with AWS services through the command line. The AWS CLI provides a unified tool to manage your AWS resources, and configuring it involves setting up your AWS credentials and default region. Here are the steps to configure the AWS CLI</p>
<h3 id="heading-step-1-install-aws-cli"><strong>Step 1: Install AWS CLI</strong></h3>
<p>Make sure you have the AWS CLI installed on your machine. You can download and install it from the official AWS CLI website.</p>
<h3 id="heading-step-2-open-a-terminal-or-command-prompt"><strong>Step 2: Open a Terminal or Command Prompt</strong></h3>
<p>Open a terminal or command prompt on your machine. The process might vary depending on your operating system.</p>
<h3 id="heading-step-3-run-aws-configure"><strong>Step 3: Run</strong> <code>aws configure</code></h3>
<p>In the terminal or command prompt, run the following command:</p>
<pre><code class="lang-basic">aws configure
</code></pre>
<h3 id="heading-step-4-enter-aws-access-key-id"><strong>Step 4: Enter AWS Access Key ID</strong></h3>
<p>You will be prompted to enter your AWS Access Key ID. This is a unique identifier associated with your AWS account. You can obtain this key from the AWS Management Console.</p>
<pre><code class="lang-basic">AWS Access <span class="hljs-keyword">Key</span> ID [None]: YOUR_ACCESS_KEY_ID
</code></pre>
<h3 id="heading-step-5-enter-aws-secret-access-key"><strong>Step 5: Enter AWS Secret Access Key</strong></h3>
<p>Next, you'll be prompted to enter your AWS Secret Access Key. This key is used to authenticate your access to AWS services.</p>
<pre><code class="lang-basic">AWS Secret Access <span class="hljs-keyword">Key</span> [None]: YOUR_SECRET_ACCESS_KEY
</code></pre>
<h1 id="heading-now-we-will-run-our-code-one-by-one-with-various-function">Now we will run our Code one by one with various function:</h1>
<h1 id="heading-1-show-the-bucket-list">1: Show the bucket list</h1>
<p>This code will list down how many bucket is already created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705615641450/e10edb82-7325-4138-b55f-73cdb3ba3752.png" alt class="image--center mx-auto" /></p>
<p>After Running the script you can see that there is no output because there is no bucket available.</p>
<p>Will create and test again the same.</p>
<p>No we have created the Test Bucket let see by script it will show up or not.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705618978538/ef29ee37-82a6-472d-bd6e-466ec698d372.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705621075373/8ea59ecf-a702-4f8c-8a56-6ba426aa76c8.png" alt class="image--center mx-auto" /></p>
<p>This code will create a New bucket.</p>
<p>And we have to uncomment the call function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705621468509/3fdf4a6e-e8ae-4cc9-a8ea-b921ed6c516d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705621658907/8741294d-969f-42d1-b8e9-4d1ed002c972.png" alt class="image--center mx-auto" /></p>
<p>As you can see there is no bucket with name <mark>testbucketboto23</mark> now i will run the code again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705621708687/4472de93-3873-40db-aaae-ff3f74118460.png" alt class="image--center mx-auto" /></p>
<p>After executing it created the Bucket</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705622306948/c29a75f9-4288-442b-9c2c-aad9c9c9ae77.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705622383917/d08aed27-0003-4793-9b2a-46fa1450ecdd.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-2upload-the-file-from-local-to-s3-bucket">2:Upload the file from local to S3 bucket.</h1>
<p>Again we will comment the create bucket function and uncomment the upload file function and run the code to upload the file from local to S3 bucket</p>
<p>Uncomment this call and function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705678474081/2d6068b7-9685-4fb9-a66e-08c2a072f6e0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705678513232/d4b92a37-105c-49c8-aa76-f154a59705c4.png" alt class="image--center mx-auto" /></p>
<p>After running the script you can see it got uploaded</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705678072202/bb32fbb6-3f25-43ea-9d36-d18da14369bc.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-3-download-the-same-file-from-s3-bucket-to-local">3: Download the same file from S3 bucket to local.</h2>
<p>For that we will delete the file from our local system.</p>
<p>Now we will uncomment the download call and function</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705678790386/9f6d7839-71ed-46f7-b905-c89fad7d88c2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705678942349/b71ff00b-0408-4f4c-85b4-f506ed09fcb0.png" alt class="image--center mx-auto" /></p>
<p>There is no file available now lets run the script.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705679240083/9a1ea151-a996-4ded-a52a-e0afc9b9864a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705679222108/4ae1cb35-2e88-4185-ae70-1f73228263c1.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-4-delete-the-file-from-s3-bucket">4: Delete the file from S3 bucket.</h1>
<p>For that we have to uncomment the function as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705679483435/042b8bf2-1d56-42d8-afa8-cff3868851b9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705679802115/504d3b96-ca15-4cc3-9e10-d0af2112964f.png" alt class="image--center mx-auto" /></p>
<p>You can see the file has been run successfully lets see over the bucket the file got deleted or not.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705679782691/ae985d5b-19dd-4832-9380-c200a1c8beb1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705679858639/88a3ccd5-ebf2-452f-91aa-08044dc9bea2.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-5-delete-the-bucket">5: Delete the bucket</h1>
<p>Now we will uncomment the delete call and function</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705681322558/977d6d20-6679-4315-b472-e4e327746133.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705681390267/58801c2a-fec0-4128-807f-e7584ff445ef.png" alt class="image--center mx-auto" /></p>
<p>After executing the code the bucket got deleted make sure you have empty the bucket before deleting you can also write the function to empty the bucket.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705681653146/11c6ebd5-3b51-4331-92ea-e3d45bd07351.png" alt class="image--center mx-auto" /></p>
<p>Thank You, please share if this articles finds you insightful.</p>
]]></content:encoded></item><item><title><![CDATA[Unveiling the Power of AWS: A Beginner's Guide]]></title><description><![CDATA[Welcome to the cloud era, where possibilities are limitless, and innovation knows no bounds. In this journey to explore the cloud, Amazon Web Services (AWS) stands tall as a pioneer, offering a robust and scalable infrastructure that has transformed ...]]></description><link>https://blog.saadkhan.co.in/unveiling-the-power-of-aws-a-beginners-guide</link><guid isPermaLink="true">https://blog.saadkhan.co.in/unveiling-the-power-of-aws-a-beginners-guide</guid><category><![CDATA[ec2instance]]></category><category><![CDATA[AWS]]></category><category><![CDATA[IAM]]></category><category><![CDATA[awsaccounts]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Thu, 18 Jan 2024 19:00:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705603893455/5c7948f5-5ac6-43af-873c-50b971673eb7.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the cloud era, where possibilities are limitless, and innovation knows no bounds. In this journey to explore the cloud, Amazon Web Services (AWS) stands tall as a pioneer, offering a robust and scalable infrastructure that has transformed the way we build and deploy applications. Let's embark on a voyage into the AWS universe, starting with the essential step – setting up your AWS account.</p>
<h2 id="heading-introduction-to-aws"><strong>Introduction to AWS</strong></h2>
<h3 id="heading-what-is-aws"><strong>What is AWS?</strong></h3>
<p>Amazon Web Services, commonly known as AWS, is a comprehensive cloud computing platform provided by Amazon. Launched in 2006, AWS has since become the backbone of countless businesses, from startups to Fortune 500 companies, offering a wide array of services that span computing power, storage, databases, machine learning, and more.</p>
<h3 id="heading-why-aws"><strong>Why AWS?</strong></h3>
<p>AWS provides a flexible and cost-effective solution for businesses and individuals looking to offload the complexities of infrastructure management. With a pay-as-you-go model, you only pay for the resources you consume, making it an attractive choice for projects of all sizes.</p>
<h2 id="heading-setting-up-your-aws-account"><strong>Setting Up Your AWS Account</strong></h2>
<h3 id="heading-step-1-creating-an-aws-account"><strong>Step 1: Creating an AWS Account</strong></h3>
<ol>
<li><p>Navigate to the <a target="_blank" href="https://aws.amazon.com/">AWS official website</a> and click on "Create an AWS Account."</p>
</li>
<li><p>Follow the on-screen instructions to provide the necessary information, including your email address, password, and account name.</p>
</li>
<li><p>Enter your payment information. Don't worry; AWS often provides a free tier with limited resources for new users to experiment and learn without incurring charges.</p>
</li>
</ol>
<h3 id="heading-step-2-securing-your-aws-account"><strong>Step 2: Securing Your AWS Account</strong></h3>
<ol>
<li><p>Once your account is created, enhance its security by enabling Multi-Factor Authentication (MFA). This adds an extra layer of protection to prevent unauthorized access.</p>
</li>
<li><p>Set up billing alerts to monitor your usage and avoid unexpected charges. AWS offers tools like AWS Budgets and AWS CloudWatch Alarms to help you stay within your budget.</p>
</li>
</ol>
<h3 id="heading-step-3-navigating-the-aws-management-console"><strong>Step 3: Navigating the AWS Management Console</strong></h3>
<ol>
<li><p>Log in to your AWS account and explore the AWS Management Console, the central hub for accessing and managing AWS services.</p>
</li>
<li><p>Familiarize yourself with the dashboard and navigation options. AWS provides a user-friendly interface, making it easy to discover and configure services.</p>
</li>
</ol>
<p>Now that your AWS account is up and running, you're ready to dive deeper into the vast array of services and unleash the true potential of cloud computing.</p>
<p>In the upcoming blog posts, we'll explore fundamental AWS services, guide you through launching virtual servers, and demonstrate how to leverage the power of AWS for hosting websites and applications.</p>
<p>Stay tuned for more insights into the world of AWS! 🚀✨</p>
]]></content:encoded></item><item><title><![CDATA[Automated CloudWatch Logs Exports to Amazon S3 using AWS Lambda]]></title><description><![CDATA[Introduction:
In the realm of cloud computing, effective log management is essential. Amazon CloudWatch Logs offers centralized log storage, while AWS Lambda provides serverless computing capabilities. Combining these services enables the automated e...]]></description><link>https://blog.saadkhan.co.in/automated-cloudwatch-logs-exports-to-amazon-s3-using-aws-lambda</link><guid isPermaLink="true">https://blog.saadkhan.co.in/automated-cloudwatch-logs-exports-to-amazon-s3-using-aws-lambda</guid><category><![CDATA[AWS]]></category><category><![CDATA[Python]]></category><category><![CDATA[#CloudWatch]]></category><category><![CDATA[S3-bucket]]></category><category><![CDATA[S3]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Wed, 17 Jan 2024 10:05:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705485882537/c3f4cf8a-c3bc-4246-a009-6ef43ca14849.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction:</h1>
<p>In the realm of cloud computing, effective log management is essential. Amazon CloudWatch Logs offers centralized log storage, while AWS Lambda provides serverless computing capabilities. Combining these services enables the automated export of logs to Amazon S3, enhancing data durability and simplifying log management workflows. In this guide, we'll walk through setting up an AWS Lambda function to streamline the process of exporting CloudWatch Logs to an S3 bucket, offering a scalable and efficient solution for organizations seeking improved log data management in the AWS ecosystem.</p>
<p>GitHub Repo: <a target="_blank" href="https://github.com/saadkhan024/Cloudwatchlogs-to-S3bucket">https://github.com/saadkhan024/Cloudwatchlogs-to-S3bucket</a></p>
<h2 id="heading-creating-a-lambda-function">Creating a Lambda function.</h2>
<p>We need to create a lambda function which will invoke with Cloudawatch</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705479086320/dd58df24-7baf-4e0b-b2f0-fbb86441426c.png" alt class="image--center mx-auto" /></p>
<p>You can select create new role as i am doing for testing purpose.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705479164826/1154c164-b752-4518-a3df-1f6becd6a973.png" alt class="image--center mx-auto" /></p>
<p>We will write some dummy function to test the case.</p>
<p>This is my Test function code</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705479602746/7211efbc-11e5-4162-b02a-36812c31cfab.png" alt class="image--center mx-auto" /></p>
<p>You can see that after executing it run successfully.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705479644439/8553c67c-0a40-4522-b8e7-c25b238c731e.png" alt class="image--center mx-auto" /></p>
<p>For checking the logs has been created or not, go to CloudWatch and check on Logs group.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705479924363/1e8d59db-b3cd-41be-aca4-2db0b4101d2d.png" alt class="image--center mx-auto" /></p>
<p>Log has been generated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705479991741/0df4b97e-b933-4d80-9b4d-d8e03fe1aa11.png" alt class="image--center mx-auto" /></p>
<p>For sending the logs from cloudwatch to s3 we will require IAM role.</p>
<h2 id="heading-creating-and-iam-role">Creating and IAM role.</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705481162963/901069f1-134a-4697-8a86-1b476fc66949.png" alt class="image--center mx-auto" /></p>
<p>and we will select the given policy and edit the trust policy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705481201482/7b3ae4ce-8222-47eb-97b1-7228191beca9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705482662977/afa0bf95-0138-44d3-95e2-e70ed370b41b.png" alt class="image--center mx-auto" /></p>
<p>We will setup the lambda function with attaching the IAM role which we have created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705482947296/4786ee74-8cb0-4baf-a71a-6ffac8e0b4c6.png" alt class="image--center mx-auto" /></p>
<p>We need to change some default configuration time to 15 min of highest.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705483079898/dc17b809-80d3-4020-8cb7-830cf879a38d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705483175234/16a95469-9996-43aa-bf01-58be774424c4.png" alt class="image--center mx-auto" /></p>
<p>Now we have to change the lambda function with our customized code and deploy.</p>
<p>you can find the code in my github repo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705483488040/6c43e5c4-3b08-4a34-92e8-059b6d8f75a6.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-creating-an-s3-bucket">Creating an S3 bucket.</h1>
<p>Go to search bar and type S3 and click on create and put the info.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705483722785/26b59136-598b-4ce0-9610-ca58f4f0f439.png" alt class="image--center mx-auto" /></p>
<p>We will edit the policy under s3 with our inline policy you can find the same on github repo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705484027500/26540623-d6d4-456f-916d-090c61319a62.png" alt class="image--center mx-auto" /></p>
<p>After deploying the script you can see that logs has been generated.</p>
<p>Thank You...</p>
]]></content:encoded></item><item><title><![CDATA[Python Real-time Project For Devops On Aws | Lambda Functions]]></title><description><![CDATA[Introduction:
As a Cloud Engineering team we take care of the AWS environment and make sure it is in compliance with the organizational policies. We use AWS cloud watch in combination with AWS Lambda to govern the resources according to the policies....]]></description><link>https://blog.saadkhan.co.in/python-real-time-project-for-devops-on-aws-lambda-functions</link><guid isPermaLink="true">https://blog.saadkhan.co.in/python-real-time-project-for-devops-on-aws-lambda-functions</guid><category><![CDATA[AWS]]></category><category><![CDATA[Python]]></category><category><![CDATA[lambda]]></category><category><![CDATA[#CloudWatch]]></category><category><![CDATA[json]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Tue, 16 Jan 2024 16:09:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705423028193/b3c53ae9-f5ca-47ec-a7c5-64536a68a250.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction:</h2>
<p>As a Cloud Engineering team we take care of the AWS environment and make sure it is in compliance with the organizational policies. We use AWS cloud watch in combination with AWS Lambda to govern the resources according to the policies. For example, we Trigger a Lambda function when an Amazon Elastic Block Store (EBS) volume is created. We use Amazon CloudWatch Events. CloudWatch Events that allows us to monitor and respond to EBS volumes that are of type GP2 and convert them to type GP3.</p>
<p>GitHub Repo: <a target="_blank" href="https://github.com/saadkhan024/Volume_gp2-to-gp3"><strong>https://github.com/saadkhan024/Volume_gp2-to-gp3</strong></a></p>
<h1 id="heading-creation-of-lambda-function">Creation of Lambda function:</h1>
<p>Go to search bar and type lambda and click on lambda under service as show below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705066754783/fde53b32-cdf6-4001-9481-ed03b3ccd3eb.png" alt class="image--center mx-auto" /></p>
<p>Then we will select create function and put the details as shown on image.</p>
<p>Under Function name you can give any name as per your requirement.</p>
<p>and under Runtime you have to select <strong><mark>Python.</mark></strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705066991430/1d07e37e-e32e-4e45-b199-7fcae7c5b709.png" alt class="image--center mx-auto" /></p>
<p>For Permission we are going with default option, you can also create an IAM role with set of permission for lambda creation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705067209643/7c017d02-77cf-41df-bdc8-a7a6785d789d.png" alt class="image--center mx-auto" /></p>
<p>Once we give the permission just hit create function and it will create the function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705067384206/3e8fa892-68eb-4f41-a1bd-65b2349bbd6c.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-testing-the-lambda-test-function">Testing the Lambda test function</h2>
<p>You have to click on Test and and under that you will find Configure test event.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705067569018/ca5bb5c3-e509-4d10-8c83-b87eeb435481.png" alt class="image--center mx-auto" /></p>
<p>After clicking on configure test event you have to given the basic details as show on below image and just click on save.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705067769420/dfac9239-093e-4d72-ade2-e3ad110caffa.png" alt class="image--center mx-auto" /></p>
<p>Once you configure the test you check the function by executing test key.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705068015767/dd7525fa-b061-4513-919e-e4b850ed2577.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-configure-cloud-watch-rule">Configure Cloud Watch rule</h1>
<p>In this section we will configure cloud watch rule which will trigger the Lambda function.</p>
<p>Go to search bar and type cloud watch and select cloud watch under services.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705068252279/7ae1e5bb-74e5-43b3-a64c-4634c8d2c943.png" alt class="image--center mx-auto" /></p>
<p>Go to <mark>Event </mark> on the left side panel and click on Rule.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705068428723/909a5be3-5c3e-4b0f-81b5-6b84c415afe1.png" alt class="image--center mx-auto" /></p>
<p>Once you click on Rules you have to click on Create Rules and follow the same which is mention below in the diagram.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705391026901/31fb74b9-c868-4387-9cb2-50b30c1c3395.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705391123085/230d9dd7-f306-4856-9828-169057dafdd9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705391183970/b2077277-4664-4ba5-b927-37b4141671bb.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705391256548/00744d0f-022e-4e3f-b01b-9c397a7150dd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705391318794/b9073660-2599-4c29-a860-2300baf2ac04.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-select-targets">Select target(s)</h1>
<p>For selecting the target follow the below step and click on next.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705391492298/0a4a9966-771c-4d89-beaf-6640c4bc62c2.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-creating-a-volume-for-testing">Creating a volume for testing.</h1>
<ol>
<li><p>Go to Ec2 Dashboard and see below the volume section click on it create one</p>
<p> volume for testing purpose.</p>
</li>
<li><p>And select gp2 partition as we are going to convert the same into gp3</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705394594611/4a26e3de-391d-4f83-9cf9-3861169e9f93.png" alt class="image--center mx-auto" /></p>
<p> Created a Volume.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705397732349/8d76f910-c503-4459-884c-3e5b03a8890c.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>You can see that Lambda function got triggered.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705404659436/aeafc580-c17b-4579-9ce2-9c6abdb95984.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-python-code-for-converting-volume-gp2-to-gp3">Python Code for converting volume gp2 to gp3</h2>
<p>Now we will write Python code to convert volume gp2 to gp3</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705420852943/076e2e13-f087-4919-9e1d-eacf4a273144.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-now-we-will-grant-the-permission-for-roles-to-get-the-access-of-ebs-volume">Now we will grant the permission for Roles to get the access of EBS volume.</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705418552120/905aaad9-db36-4836-994e-1486a09eb574.png" alt class="image--center mx-auto" /></p>
<p>You fill find the roles like below, click on it and attach the policy to it.</p>
<p>Kindly select <mark> Create inline policy.</mark></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705418639970/1273ced2-aa81-4f35-bafc-d684f0eb1328.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705418726014/bdf70499-f416-4075-aac1-bec995c4b853.png" alt class="image--center mx-auto" /></p>
<p>I am going with all the permission as it is demo one. you can restrict the access.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705419125409/2ef89b72-d62b-4343-ac69-55070febf5d2.png" alt class="image--center mx-auto" /></p>
<p>Provide the Policy Name and click on Create</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705419230212/d474698d-2d5d-42e6-9287-ed9173041eb4.png" alt class="image--center mx-auto" /></p>
<p>Now we will delete the volume which we have created as policy will triggered wen we create a Volume, so for that we required to create one.</p>
<p>Created new volume let see if policy has been triggered or not.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705419407896/9baf5255-937c-4f7a-aa65-47389aa0b428.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-policy-has-been-triggered-successfully-and-you-can-see-that-it-has-been-converted-to-gp3">Policy has been triggered successfully and you can see that it has been converted to "gp3"</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705420721890/c8adfb4b-2410-42b5-aa82-56a4c3010fe1.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-thank-you-please-share-if-you-find-helpful">Thank You. please share if you find helpful.</h2>
]]></content:encoded></item><item><title><![CDATA[Automating EC2 Instance Deployment on AWS with Python]]></title><description><![CDATA[Introduction:
In the fast-paced world of cloud computing, the ability to efficiently deploy resources on platforms like Amazon Web Services (AWS) is crucial. As a developer or system administrator, streamlining the process of creating EC2 instances c...]]></description><link>https://blog.saadkhan.co.in/automating-ec2-instance-deployment-on-aws-with-python</link><guid isPermaLink="true">https://blog.saadkhan.co.in/automating-ec2-instance-deployment-on-aws-with-python</guid><category><![CDATA[AWS]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[Python]]></category><category><![CDATA[EC2 instance]]></category><category><![CDATA[command line]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Thu, 11 Jan 2024 13:14:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704978682475/5d56ed1d-e34d-4d9c-a2e3-8291d57733c9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction:</h2>
<p>In the fast-paced world of cloud computing, the ability to efficiently deploy resources on platforms like Amazon Web Services (AWS) is crucial. As a developer or system administrator, streamlining the process of creating EC2 instances can save time and enhance productivity. This blog post introduces a Python script designed to automate the deployment of EC2 instances on AWS.</p>
<h1 id="heading-you-can-find-the-script-on-my-github-repository">You can find the script on my GitHub repository.</h1>
<p><a target="_blank" href="https://github.com/saadkhan024/Python_script_Ec2">https://github.com/saadkhan024/Python_script_Ec2</a></p>
<h3 id="heading-problem-statement"><strong>Problem Statement:</strong></h3>
<p>While working with cloud infrastructure, one common pain point faced by developers and administrators is the manual and repetitive process of provisioning EC2 instances on AWS. The traditional approach often involves navigating through the AWS Management Console, configuring various settings, and waiting for the instance to be ready. This manual process can be time-consuming, prone to human error, and hinder the scalability of cloud-based projects.</p>
<h3 id="heading-solution"><strong>Solution:</strong></h3>
<p>To address the challenges associated with manual EC2 instance deployment on AWS, I have developed a Python script leveraging the Boto3 library. Boto3 is the official AWS SDK for Python, providing a convenient and programmatic interface to interact with AWS services.</p>
<p>Before diving into the details, make sure to install the Boto3 library by running: `</p>
<p><strong><mark>pip install boto3</mark></strong></p>
<h4 id="heading-aws-configuration"><strong>AWS Configuration:</strong></h4>
<p>The script starts by configuring the AWS region and providing the necessary access credentials. Replace <code>#your-aws-region</code>, <code>#your-access-key</code>, and <code>#your-secret-key</code> with your specific AWS region and credentials.</p>
<p>region = #your-aws-region access_key = #your-access-key secret_key = #your-secret-key</p>
<p>ec2 = boto3.client('ec2', region_name=region, aws_access_key_id=access_key, aws_secret_access_key=secret_key)</p>
<h4 id="heading-instance-parameters"><strong>Instance Parameters:</strong></h4>
<p>Next, define the parameters for the EC2 instance you want to create. Customize the <code>ImageId</code>, <code>InstanceType</code>, <code>KeyName</code>, and other parameters according to your specific requirements.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704978247054/563f54a5-57a8-4674-aa93-375ad3546583.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-instance-creation"><strong>Instance Creation:</strong></h4>
<p>response = <a target="_blank" href="http://ec2.run">ec2.run</a>_instances(**instance_params) instance_id = response['Instances'][0]['InstanceId'] print(f"Instance {instance_id} is being created.")</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704978317704/becdc3ff-c962-4709-b82d-2f37609b69f1.png" alt class="image--center mx-auto" /></p>
<p>This script provides a streamlined and automated solution to deploy EC2 instances on AWS. In the next section, we will explore the usage of this script and guide you through the process of running it to launch an EC2 instance effortlessly.</p>
<p><strong>Feel free to further customize and expand this section based on additional details you'd like to provide about the script and its capabilities.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Deploying a Python-based Microservice Application on AWS EKS]]></title><description><![CDATA["Unlock the power of AWS EKS with this step-by-step guide! Learn how to effortlessly deploy a Python-based microservice application on Amazon's Elastic Kubernetes Service (EKS), harnessing the scalability and efficiency of containers in the cloud. Di...]]></description><link>https://blog.saadkhan.co.in/deploying-a-python-based-microservice-application-on-aws-eks</link><guid isPermaLink="true">https://blog.saadkhan.co.in/deploying-a-python-based-microservice-application-on-aws-eks</guid><category><![CDATA[AWS]]></category><category><![CDATA[Python]]></category><category><![CDATA[EKS]]></category><category><![CDATA[Docker]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[rabbitmq]]></category><category><![CDATA[IAM]]></category><dc:creator><![CDATA[Saad Khan]]></dc:creator><pubDate>Mon, 01 Jan 2024 14:19:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704023376732/dcc52ec5-b429-478d-a56a-bbf92905aed3.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>"Unlock the power of AWS EKS with this step-by-step guide! Learn how to effortlessly deploy a Python-based microservice application on Amazon's Elastic Kubernetes Service (EKS), harnessing the scalability and efficiency of containers in the cloud. Dive into the essentials of seamless deployment, optimizing your workflow for a robust, scalable, and dynamic application environment."</p>
<p>Credits for Video <a target="_blank" href="https://www.linkedin.com/in/nasiullha-chaudhari/"><strong>Nasiullha Chaudhari</strong></a></p>
<p>YouTube video: <a target="_blank" href="https://youtu.be/jHlRqQzqB_Y?si=oVjnBLWD5JEs_dFW"><strong>https://youtu.be/jHlRqQzqB_Y?si=oVjnBLWD5JEs_dFW</strong></a></p>
<p>GitHub Repo: <a target="_blank" href="https://github.com/N4si/microservices-python-app">https://github.com/N4si/microservices-python-app</a></p>
<p>Articles Credit: <a target="_blank" href="https://hashnode.com/@se7enAj"><strong>Ajay Kumar Yegireddi</strong></a></p>
<p>For EKS,IAM,Node creation via Script refer video by Ajay Kumar: <a target="_blank" href="https://www.youtube.com/watch?v=5-PZnYaoZUM">https://www.youtube.com/watch?v=5-PZnYaoZUM</a></p>
<p>For Starting with we need to have some pre-requisite.</p>
<ol>
<li><p>AWS Instance-- Kindly go with t2.medium OS Ubuntu and Version would be 20.04 because its is stable version for kubectl.</p>
</li>
<li><p>HELM</p>
</li>
<li><p>AWS CLI</p>
</li>
<li><p>Python</p>
</li>
<li><p>Install kubectl</p>
</li>
<li><p>Database: MongoDB and PostgreSQL</p>
</li>
</ol>
<p>Once you done with creation of AWS instance installation of required package mentioned above you can wit creating of IAM role.</p>
<h1 id="heading-created-a-ec2-instances">Created a EC2 Instances</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704033129793/c4f5c494-6e2f-40ca-9353-0a9e88585288.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-iam-role-creation">IAM role creation</h2>
<p>Click on Search filed, type IAM</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704033352882/de422d44-8362-41a6-abf3-664488ce1b13.png" alt class="image--center mx-auto" /></p>
<p>Click on "Role"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704033758045/e85f0dab-b82f-499b-befd-6e19080e7023.png" alt class="image--center mx-auto" /></p>
<p>Click on AWS Service</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704033880301/2a90327b-b793-4235-9b0d-f21d56be6492.png" alt class="image--center mx-auto" /></p>
<p>Search for "EC2" and Click on "Next"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704034071170/8f5e6bf8-501d-40ad-b73c-ec46b38e42ba.png" alt class="image--center mx-auto" /></p>
<p>Now, search of <strong><mark>AdministratorAccess</mark></strong> &amp; select as seen on below image.</p>
<p>and Click on "Next"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704034365923/b6b4a664-d7c6-4cd3-ac19-8f6a6491c91d.png" alt class="image--center mx-auto" /></p>
<p>On the Role name, give name as you require and</p>
<p>Click on <strong><mark>Create Role</mark></strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704034676537/3bfa9b6b-7232-44e6-b3b0-28c05040df4f.png" alt class="image--center mx-auto" /></p>
<p>After creation of IAM role go to <strong><mark>EC2 Instance</mark></strong></p>
<p>and follow the below step</p>
<p>Select instance --&gt; Actions --&gt; Security --&gt; Modify IAM role</p>
<p>&amp; click on Update IAM role.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704035091119/ef59ed59-c31b-4a69-afef-4fbd09bb2f46.png" alt class="image--center mx-auto" /></p>
<p>Now you can connect to the server.</p>
<p>Once you login to the server you can fork the repo and make a clone of it by executing below command.</p>
<p>#git clone "repo url"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704035626424/cd68b678-efcd-4569-a6e7-3855ecdae169.png" alt class="image--center mx-auto" /></p>
<p>Check Version by executing below command.</p>
<pre><code class="lang-basic"># Check Versions
terraform -version
kubectl version --client --short
aws --version
helm version --short
python3 --version
psql --version
mongod --version
docker version
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704080722639/17176746-d24b-485e-b4c5-a1ee98cfc068.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704080900194/47d0c6a1-edb1-460b-9911-ea05bc905578.png" alt class="image--center mx-auto" /></p>
<p>Now go inside Eks-terraform to provison Eks cluster with terraform files</p>
<p>Now you can see terraform files and make sure to change your region and <mark>S3 bucket name in the backend file.</mark></p>
<p>Now initialize</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704081309953/9e435d7a-d04c-4680-855c-8c87d28babc7.png" alt class="image--center mx-auto" /></p>
<p>Validate the code</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704082617823/29cb1af4-7e39-468b-9f09-2aecb848adbf.png" alt class="image--center mx-auto" /></p>
<p>Now let's see plan</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704082968297/2b524769-76a4-4d9c-80b4-41f072f214fe.png" alt class="image--center mx-auto" /></p>
<p>Let's apply to provision by executing below command</p>
<p>#terraform apply --auto-approve</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704098821923/00e90866-72ce-49da-9fd7-7f875474fd78.png" alt class="image--center mx-auto" /></p>
<p>It take some time to complete the process. After completion there will be one EKS cluster, IAM role for EKS and Node Server will be created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704098863782/df733fc9-b53a-42b3-a8f7-5693059c95f5.png" alt class="image--center mx-auto" /></p>
<p>EC2 Instance:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704099070959/ef538fa9-b3f1-44e7-87c4-63cbe0afaa61.png" alt class="image--center mx-auto" /></p>
<p>EKS Cluster created</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704099169126/442b5b1b-7265-4da5-98f2-28069aa35053.png" alt class="image--center mx-auto" /></p>
<p>IAM Role:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704099290074/dc8254c9-94d0-4568-98ad-dd61c5111eae.png" alt class="image--center mx-auto" /></p>
<p>Will update the Kubernetes configuration by executing below command</p>
<p>#aws eks update-kubeconfig --name --region</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704099529879/1d4c689c-380b-40f7-b282-17bf8749d425.png" alt class="image--center mx-auto" /></p>
<p>Let's go inside the Helm_charts</p>
<pre><code class="lang-basic">cd Helm_charts
ls
</code></pre>
<p>Now go inside MongoDB and apply the k8s files</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704106758818/cbdf63f9-2321-4873-a108-83711a2616e4.png" alt class="image--center mx-auto" /></p>
<p>No execute the below command</p>
<pre><code class="lang-basic">kubectl <span class="hljs-keyword">get</span> all
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704107210748/5b0a876f-c51b-448b-8246-18faf2b7deb1.png" alt class="image--center mx-auto" /></p>
<p>To check the Persistent volume</p>
<pre><code class="lang-basic">kubectl <span class="hljs-keyword">get</span> pv
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704107349339/c423de74-c1a2-481b-bc15-ae82e029eb37.png" alt class="image--center mx-auto" /></p>
<p>Then go to Postgres folder and edit the init.sql file</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704107500769/38b938c1-9e9d-4ff0-9b26-1b918b2a62f4.png" alt class="image--center mx-auto" /></p>
<p>Enter your email and password</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704108493206/35220b58-e21e-456a-9e59-fbe2b0ddb445.png" alt class="image--center mx-auto" /></p>
<p>Apply the Kubernetes files using Helm</p>
<pre><code class="lang-basic">helm install postgres .
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704108715849/8372460e-64d2-46c6-86bc-b7ed177af55d.png" alt class="image--center mx-auto" /></p>
<p>Let's see the pods and deployments</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704108925176/a2b42d00-d179-4bff-992d-8b0d034022ce.png" alt class="image--center mx-auto" /></p>
<p>Add some rules to Node Server</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704109334028/2b562d54-02f1-49ef-82d9-9e31c376ab18.png" alt class="image--center mx-auto" /></p>
<p>Now copy the public IP of the Node group ec2 instance and execute below command.</p>
<pre><code class="lang-basic">mongosh mongodb://&lt;username&gt;:&lt;pwd&gt;@&lt;nodeip&gt;:<span class="hljs-number">30005</span>/mp3s?authSource=admin
#username use nasi
#pwd nasi1234    #<span class="hljs-keyword">if</span> you want <span class="hljs-keyword">to</span> update them go <span class="hljs-keyword">to</span> mongo secrets.yml file <span class="hljs-keyword">and</span> update
#nodeip #use your node ec2 instance ip
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704109716118/a8a0087c-d845-4981-b1c0-6e5138c13c38.png" alt class="image--center mx-auto" /></p>
<p>Connect to the Postgres database and copy all the queries from the "init.sql" file.</p>
<p>Now add the init.sql file and Use your mail for values</p>
<pre><code class="lang-basic">CREATE TABLE auth_user (
    id integer GENERATED ALWAYS AS IDENTITY PRIMARY <span class="hljs-keyword">KEY</span>,
    email VARCHAR (<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> NULL,
    password VARCHAR (<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> NULL
);

--Add Username <span class="hljs-keyword">and</span> Password <span class="hljs-keyword">for</span> Admin User
-- INSERT INTO auth_user (email, password) VALUES (<span class="hljs-comment">'thomasfookins007helby@gmail.com', '123456');</span>
INSERT INTO auth_user (email, password) VALUES (<span class="hljs-comment">'&lt;User your mail&gt;', '123456');</span>
</code></pre>
<p>Now provide \d to see data tables</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704110310747/5f6be2b7-918f-4fa6-8966-e46f76103b00.png" alt class="image--center mx-auto" /></p>
<p>Now provide the below command to see the authentication user</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704110393296/952dbda4-8726-4b0e-82eb-f9efe81f7a15.png" alt class="image--center mx-auto" /></p>
<p>Now go to RabbitMQ directory</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704110550520/d7f1c3a1-9766-48f9-9c36-c8d3ebd606d0.png" alt class="image--center mx-auto" /></p>
<p>And execute below command</p>
<pre><code class="lang-basic">helm install rabbit .
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704110665957/f2ab381d-c4ff-42a4-89ec-0fa86c72258e.png" alt class="image--center mx-auto" /></p>
<p>Now see the deployments and pods</p>
<pre><code class="lang-basic">kubectl <span class="hljs-keyword">get</span> all
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704110932491/24509896-3b60-4275-8169-8c1060869f42.png" alt class="image--center mx-auto" /></p>
<p>Now copy the public IP of the node group Ec2 instance</p>
<pre><code class="lang-basic">&lt;Node-ec2-public-ip:<span class="hljs-number">30004</span>&gt;
</code></pre>
<p>You will get this page Just login</p>
<pre><code class="lang-basic">username is guest
password is guest
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704111172500/447e2b86-3832-4da0-8cfe-d49df791a715.png" alt class="image--center mx-auto" /></p>
<p>This will the dashboard once you will login</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704111238533/18c13395-0020-4e9f-b5ee-d32a7709e7db.png" alt class="image--center mx-auto" /></p>
<p>Click on Queues</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704111351456/2026e137-e99b-4b05-9deb-81f64d842acc.png" alt class="image--center mx-auto" /></p>
<p>After Queue for Mp3 and Video it will show like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704111714544/a24b5352-9292-433a-ad05-1af097c4c918.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-microservices"><strong>Microservices</strong></h3>
<p>Got to SRC directory as shown below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704111832609/9b228bdf-b7b2-46be-9405-fc6cf25e4971.png" alt class="image--center mx-auto" /></p>
<p>Go to directory as shown below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704111964669/694fb144-163e-43ec-a371-e15cd1cd3df8.png" alt class="image--center mx-auto" /></p>
<p>Now let's see whether it created pods or not</p>
<pre><code class="lang-basic">kubectl <span class="hljs-keyword">get</span> all
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704112062389/575463fd-1192-4e8f-a734-501b7b667eb8.png" alt class="image--center mx-auto" /></p>
<p>Now come back to another Microservice and do the same process</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704112181802/3330488b-7662-484a-a2b9-2d61aa2db3a6.png" alt class="image--center mx-auto" /></p>
<p>And execute below command</p>
<pre><code class="lang-basic">kubectl apply -f .
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704112318201/559d94a4-12b4-4dc1-be78-ab17b601f5ae.png" alt class="image--center mx-auto" /></p>
<p>Now come back to another microservice and do the same process</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704112472645/09425951-792c-4590-8220-3c0452c1be0e.png" alt class="image--center mx-auto" /></p>
<p>And execute the below command</p>
<pre><code class="lang-basic">kubectl apply -f .
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704112704956/ae5893e2-e0da-4302-88ae-74af9fd53801.png" alt class="image--center mx-auto" /></p>
<p>Check for deployments and service</p>
<pre><code class="lang-basic">kubectl <span class="hljs-keyword">get</span> all
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704112831476/92e4efe5-9123-48fb-a06d-c3b3c410da38.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-gmail-password"><strong>GMAIL PASSWORD</strong></h3>
<p>Now let's create a Password for Gmail to get Notifications</p>
<p>Open your Gmail account in the browser and click on your profile top right.</p>
<p>Click on Manage your Google account</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704112976554/8b82af59-4a86-4501-baa4-2096dad2b375.png" alt class="image--center mx-auto" /></p>
<p>Now click on Security</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704113060047/2457457f-cb12-47e4-a8f6-854be08afd54.png" alt class="image--center mx-auto" /></p>
<p>Two-step verification should be enabled<br />If not, enable it</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704113261244/30d557da-69e2-4143-be7a-c72e8cd6b52e.png" alt class="image--center mx-auto" /></p>
<p>Now click on the search bar and <mark>search for the APP</mark></p>
<p>Click on App passwords</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704113339883/416469d2-1a72-409d-b017-ac857badc24e.png" alt class="image--center mx-auto" /></p>
<p>Come back to Putty and update the secret.yaml file for notification service microservice</p>
<pre><code class="lang-basic">cd ../..
cd notification-service
cd manifest
sudo vi secret.yaml
#change your mail <span class="hljs-keyword">and</span> password that Generated.
</code></pre>
<p>vi secret.yaml</p>
<p>apiVersion: v1 kind: Secret metadata: name: notification-secret stringData: GMAIL_ADDRESS: "<a target="_blank" href="mailto:projectsdevops8@gmail.com">projectsdevops8@gmail.com</a>" GMAIL_PASSWORD: "your generated password" type: Opaque</p>
<p>Now apply the manifest files</p>
<pre><code class="lang-basic">kubectl apply -f .
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704114088542/ab5ef364-4272-4b34-9ae1-21e711301d74.png" alt class="image--center mx-auto" /></p>
<p>Now come to the assets directory</p>
<pre><code class="lang-basic">cd /home/ubuntu/microservice-python-app
cd assets
ls
curl -X POST http://nodeIP:<span class="hljs-number">30002</span>/login -u &lt;email&gt;:&lt;password&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704116458590/57630233-4f72-487b-b51a-e37a881011a4.png" alt class="image--center mx-auto" /></p>
<p>Copy the token and paste it inside a base 64 decoder you will get this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704116875997/5fae34cd-de80-4cbd-874a-917a72dd065d.png" alt class="image--center mx-auto" /></p>
<p>change JWT Token and node ec2 IP.</p>
<pre><code class="lang-basic"> curl -X POST -F <span class="hljs-comment">'file=@./video.mp4' -H 'Authorization: Bearer &lt;JWT Token&gt;' http://nodeIP:30002/upload</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704118082266/3b954d89-e904-4d05-9263-05ea9e5d5146.png" alt class="image--center mx-auto" /></p>
<p>It will send an ID to the mail</p>
<p>Let's check the mail</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704118126265/dfd12729-9367-4a28-bb0d-1d80de514d0b.png" alt class="image--center mx-auto" /></p>
<p>Copy that ID and paste it inside the below command with the JWT token and fid</p>
<pre><code class="lang-basic">curl --output video.mp3 -X <span class="hljs-keyword">GET</span> -H <span class="hljs-comment">'Authorization: Bearer ' "http://nodeIP:30002/download?fid="</span>
#change Bearer with JWT token
#nodeIp
#fid token at <span class="hljs-keyword">end</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704118361875/14d23abb-3d2e-4893-ad10-8623828e49fa.png" alt class="image--center mx-auto" /></p>
<p>It will download an MP3 file</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704118465974/9585a526-518a-46c4-870e-0065242fa41e.png" alt class="image--center mx-auto" /></p>
<p>You can see it's created mp3 file and you can play it.</p>
<pre><code class="lang-basic">aws s3 cp your-file s3://your-bucket/your-prefix/
</code></pre>
<p>You can copy it s3 bucket and download and you can listen to it.</p>
<h3 id="heading-destroy"><strong>Destroy</strong></h3>
<p>Now go inside Eks-terraform directory</p>
<p>To delete eks cluster</p>
<pre><code class="lang-basic">terraform destroy --<span class="hljs-keyword">auto</span>-approve
</code></pre>
<p>It will take 10 minutes to delete the cluster</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704118655194/f7a77124-8d9f-4a62-9b98-08d9fa00f453.png" alt class="image--center mx-auto" /></p>
<p>Once that is done<br />Remove your Ec2 instance and Iam role.</p>
<h1 id="heading-thank-you">Thank You...!</h1>
]]></content:encoded></item></channel></rss>