<?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[Apurv Gujjar]]></title><description><![CDATA[Explore DevOps, AWS, Kubernetes, Docker, Terraform, Linux, and Cloud Engineering through hands-on projects, practical guides, interview preparation, certification resources, and real-world learning by Apurv Gujjar.
DevOps
AWS
Cloud Computing
Kubernetes
Docker
Terraform
Linux
Jenkins
GitHub Actions
CI/CD
Prometheus
Grafana
Python
Cloud Engineer
DevOps Engineer
AWS Certification
Learn DevOps with practical tutorials, real-world projects, GitLab, Docker, Kubernetes, Terraform, AWS, GCP, CI/CD, Linux, certification guides, and interview preparation by Apurv Gujjar.]]></description><link>https://apurv-gujjar.me</link><image><url>https://cdn.hashnode.com/uploads/logos/685cdc0d5ca95e55fac3ab09/0b89e2cd-8c98-48fd-af7e-90e43519cebf.png</url><title>Apurv Gujjar</title><link>https://apurv-gujjar.me</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 04 Sep 2026 23:48:51 GMT</lastBuildDate><atom:link href="https://apurv-gujjar.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Day  6 : Variables, Secrets, Artifacts & Complete CI/CD Workflow ]]></title><description><![CDATA[Master GitLab CI/CD Variables, Secrets Management, Artifacts & Best Practices
📖 Introduction
In the previous article, we learned how GitLab Runners execute CI/CD pipelines and how to configure Self-H]]></description><link>https://apurv-gujjar.me/day-6-variables-secrets-artifacts-complete-ci-cd-workflow</link><guid isPermaLink="true">https://apurv-gujjar.me/day-6-variables-secrets-artifacts-complete-ci-cd-workflow</guid><category><![CDATA[GitLab]]></category><category><![CDATA[GitLab-CI]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Security]]></category><category><![CDATA[variables]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 26 Jul 2026 08:41:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/48e7df75-73b2-4923-9dc1-28b8084e258f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Master GitLab CI/CD Variables, Secrets Management, Artifacts &amp; Best Practices</strong></p>
<h3>📖 Introduction</h3>
<p>In the previous article, we learned how GitLab Runners execute CI/CD pipelines and how to configure Self-Hosted Runners.</p>
<p>Now it's time to learn one of the most important topics in GitLab CI/CD—<strong>Variables, Secrets, and Artifacts</strong>.</p>
<p>Instead of hardcoding sensitive information like API keys, passwords, or cloud credentials, GitLab provides a secure way to manage them using CI/CD Variables. You'll also learn how to store build outputs using Artifacts and follow best practices for building secure and maintainable pipelines.</p>
<p>By the end of this article, you'll be able to create more secure, production-ready GitLab CI/CD pipelines.</p>
<h3>🎯 What You'll Learn</h3>
<p>After completing this article, you'll understand:</p>
<ul>
<li><p>✅ What are CI/CD Variables?</p>
</li>
<li><p>✅ Protected Variables</p>
</li>
<li><p>✅ Masked Variables</p>
</li>
<li><p>✅ Expanded Variables</p>
</li>
<li><p>✅ Secrets Management</p>
</li>
<li><p>✅ Artifacts</p>
</li>
<li><p>✅ Artifact Expiry</p>
</li>
<li><p>✅ Common CI/CD Errors</p>
</li>
<li><p>✅ CI/CD Best Practices</p>
</li>
</ul>
<h3>📚 Prerequisites</h3>
<p>Before continuing, make sure you have:</p>
<ul>
<li><p>A GitLab account</p>
</li>
<li><p>A GitLab repository</p>
</li>
<li><p>A working GitLab CI/CD pipeline</p>
</li>
<li><p>Basic knowledge of GitLab CI/CD</p>
</li>
</ul>
<h3>🔐 What are CI/CD Variables?</h3>
<p>CI/CD Variables are key-value pairs used to store configuration values and sensitive information securely. Instead of hardcoding values inside the <code>.gitlab-ci.yml</code> file, you can store them as variables and use them during pipeline execution.</p>
<p>For example, instead of writing an API key directly in your pipeline, you can reference it as a variable.</p>
<pre><code class="language-yaml">variables:
  APP_NAME: "GitLab Practice"

build:
  script:
    - echo $APP_NAME
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/5f8b21ec-655a-4691-9ac0-0ab12af2c21b.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f503473a-b9cc-49da-97a1-4c4ef28e2589.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c1c4091a-69cb-49c8-9c97-95db42d1428e.png" alt="" style="display:block;margin:0 auto" />

<h3>🛡️ Protected Variables</h3>
<p>Protected Variables are only available to pipelines running on <strong>protected branches</strong> or <strong>protected tags</strong>.</p>
<p>They are commonly used for production credentials such as:</p>
<ul>
<li><p>Production API Keys</p>
</li>
<li><p>Database Passwords</p>
</li>
<li><p>Cloud Credentials</p>
</li>
</ul>
<p>This prevents sensitive data from being exposed in feature branches.</p>
<h3>🙈 Masked Variables</h3>
<p>Masked Variables hide sensitive values from pipeline logs.</p>
<p>For example, if a variable contains an API key or password, GitLab replaces the actual value with <code>****</code> in the job logs.</p>
<p>This helps prevent accidental exposure of secrets.</p>
<h3>🔄 Expanded Variables</h3>
<p>Expanded Variables allow one variable to reference another.</p>
<p>Example:</p>
<pre><code class="language-yaml">variables:
  APP_NAME: "gitlab-app"
  IMAGE_NAME: "$APP_NAME:v1"
</code></pre>
<p>GitLab automatically expands the referenced value during pipeline execution.</p>
<h3>🔑 Secrets Management</h3>
<p>Sensitive information such as passwords, API keys, AWS credentials, and database URLs should never be stored directly in your repository.</p>
<p>Instead, save them in <strong>Settings → CI/CD → Variables</strong> and reference them inside your pipeline.</p>
<pre><code class="language-yaml">deploy:
  script:
    - echo "$AWS_ACCESS_KEY_ID"
</code></pre>
<h3>📦 Artifacts</h3>
<p>Artifacts are files generated during a pipeline that can be stored and downloaded after a job completes.</p>
<p>Common examples include:</p>
<ul>
<li><p>Build output</p>
</li>
<li><p>Reports</p>
</li>
<li><p>Log files</p>
</li>
<li><p>Test results</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="language-yaml">build:
  script:
    - mkdir dist
    - echo "Build Complete" &gt; dist/output.txt

  artifacts:
    paths:
      - dist/
</code></pre>
<h3>⏳ Artifact Expiry</h3>
<p>Artifacts can be configured to expire automatically after a specific period.</p>
<pre><code class="language-yaml">artifacts:
  paths:
    - dist/
  expire_in: 7 days
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/701fcf30-87a4-481f-910b-a952ec9ded94.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b1b6cad0-a099-499f-9ac3-de75d6cbd2f6.png" alt="" style="display:block;margin:0 auto" />

<h3>⚠️ Common CI/CD Errors</h3>
<p>Some common issues you may encounter include:</p>
<ul>
<li><p><strong>Invalid</strong> <code>.gitlab-ci.yml</code> <strong>syntax</strong></p>
</li>
<li><p><strong>Runner Offline</strong></p>
</li>
<li><p><strong>Missing CI/CD Variables</strong></p>
</li>
<li><p><strong>Permission Denied</strong></p>
</li>
<li><p><strong>Pipeline Failed</strong></p>
</li>
</ul>
<p>Review the pipeline logs to identify and resolve these errors quickly.</p>
<h3>✅ Best Practices</h3>
<ul>
<li><p>Store secrets using CI/CD Variables.</p>
</li>
<li><p>Never hardcode passwords or tokens.</p>
</li>
<li><p>Use Protected Variables for production.</p>
</li>
<li><p>Mask sensitive credentials.</p>
</li>
<li><p>Configure artifact expiry.</p>
</li>
<li><p>Validate your <code>.gitlab-ci.yml</code> before deployment.</p>
</li>
</ul>
<h3>🎯 Summary</h3>
<p>Congratulations! 🎉 You have completed <strong>Day 6</strong> of the GitLab learning series.</p>
<p>In this article, you learned how to securely manage <strong>CI/CD Variables</strong>, protect sensitive information using <strong>Protected</strong> and <strong>Masked Variables</strong>, use <strong>Artifacts</strong> to store build outputs, configure <strong>Artifact Expiry</strong>, and follow CI/CD best practices for production-ready pipelines.</p>
<h2>🎉 Congratulations!</h2>
<p>You have successfully completed the <strong>GitLab DevOps Learning Series</strong>.</p>
<p>You now have a solid understanding of GitLab fundamentals, repositories, CI/CD pipelines, GitLab Runners, Variables, Secrets, and Artifacts. These concepts provide a strong foundation for building secure and production-ready DevOps workflows using GitLab.</p>
]]></content:encoded></item><item><title><![CDATA[Day 5 : GitLab Runners & Pipeline Execution]]></title><description><![CDATA[Learn GitLab Runners, Hosted vs Self-Hosted Runners, Runner Registration, Tags, Pipeline Editor & Parallel Jobs
📖 Introduction
In the previous article, we created our first GitLab CI/CD pipeline and ]]></description><link>https://apurv-gujjar.me/day-5-gitlab-runners-pipeline-execution</link><guid isPermaLink="true">https://apurv-gujjar.me/day-5-gitlab-runners-pipeline-execution</guid><category><![CDATA[GitLab]]></category><category><![CDATA[Devops]]></category><category><![CDATA[cicd]]></category><category><![CDATA[GitLab-CI]]></category><category><![CDATA[version control systems]]></category><category><![CDATA[Linux]]></category><category><![CDATA[AWS]]></category><category><![CDATA[ec2]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 26 Jul 2026 08:36:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/083710f5-075b-44d9-95f4-9dfd57a83953.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Learn GitLab Runners, Hosted vs Self-Hosted Runners, Runner Registration, Tags, Pipeline Editor &amp; Parallel Jobs</h3>
<h3>📖 Introduction</h3>
<p>In the previous article, we created our first GitLab CI/CD pipeline and learned how pipelines, stages, and jobs work.</p>
<p>But one important question remains:</p>
<p><strong>Who actually executes these pipeline jobs?</strong></p>
<p>The answer is <strong>GitLab Runner</strong>.</p>
<p>A GitLab Runner is responsible for executing the jobs defined in your <code>.gitlab-ci.yml</code> file. Whenever a pipeline is triggered, GitLab assigns the jobs to an available runner, which performs the required tasks and reports the results back to GitLab.</p>
<p>In this article, you'll learn how GitLab Runners work, the difference between Hosted and Self-Hosted Runners, how to register a runner, use runner tags, and optimize pipelines with parallel jobs.</p>
<h3>🎯 What You'll Learn</h3>
<p>After completing this article, you'll understand:</p>
<ul>
<li><p>✅ What is a GitLab Runner?</p>
</li>
<li><p>✅ Why GitLab Runners are Required</p>
</li>
<li><p>✅ How GitLab Runners Work</p>
</li>
<li><p>✅ GitLab Runner Architecture</p>
</li>
<li><p>✅ Hosted Runner vs Self-Hosted Runner</p>
</li>
<li><p>✅ Registering a GitLab Runner</p>
</li>
<li><p>✅ Runner Tags</p>
</li>
<li><p>✅ Pipeline Editor</p>
</li>
<li><p>✅ Parallel Jobs</p>
</li>
</ul>
<h3>📚 Prerequisites</h3>
<p>Before continuing, make sure you have:</p>
<ul>
<li><p>A GitLab account</p>
</li>
<li><p>A GitLab repository</p>
</li>
<li><p>A working GitLab CI/CD pipeline (Day 4)</p>
</li>
<li><p>Basic knowledge of Git and GitLab</p>
</li>
</ul>
<h3>🚀 What is a GitLab Runner?</h3>
<p>A <strong>GitLab Runner</strong> is an application that executes the jobs defined in your <code>.gitlab-ci.yml</code> file.</p>
<p>Whenever a pipeline is triggered, GitLab sends the job to an available runner. The runner executes the commands, collects the results, and sends the status back to GitLab.</p>
<p>Without a GitLab Runner, a pipeline cannot execute any jobs.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/bf61a608-2d7e-49c1-9473-5132d5a95508.png" alt="" style="display:block;margin:0 auto" />

<h3>❓ Why Do We Need a GitLab Runner?</h3>
<p>GitLab is responsible for creating and managing pipelines, but it <strong>does not execute the jobs itself</strong>.</p>
<p>Whenever a pipeline is triggered, GitLab sends each job to an available <strong>GitLab Runner</strong>. The runner then executes the commands defined in the <code>.gitlab-ci.yml</code> file and returns the results to GitLab.</p>
<p>Without a runner, the pipeline will remain in a <strong>Pending</strong> state because there is no machine available to execute the jobs.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c8c0dab7-4cdd-4e94-ac7d-614a483a7576.png" alt="" style="display:block;margin:0 auto" />

<h3>⚙️ How GitLab Runner Works</h3>
<p>Whenever a developer pushes code, GitLab creates a pipeline based on the <code>.gitlab-ci.yml</code> file. It then assigns each job to an available GitLab Runner.</p>
<p>The runner executes the job, collects the output, and sends the execution status back to GitLab. The pipeline is updated automatically with the job results.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/34e2daea-4f25-4111-a2c3-5bc53a38edb1.png" alt="" style="display:block;margin:0 auto" />

<h3>🏛️ GitLab Runner Architecture</h3>
<p>GitLab Runner works as a bridge between <strong>GitLab</strong> and the machine where your jobs are executed.</p>
<p>When a pipeline is triggered, GitLab sends the job to an available runner. The runner uses an <strong>Executor</strong> (such as Docker or Shell) to execute the job and then sends the results back to GitLab.</p>
<p>The architecture looks like this:</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/138647b4-cc87-4541-b78e-173ee12f8831.png" alt="" style="display:block;margin:0 auto" />

<h2>🧩 Components of the Architecture</h2>
<ul>
<li><p><strong>GitLab Server</strong> → Creates and manages pipelines.</p>
</li>
<li><p><strong>GitLab Runner</strong> → Receives and executes jobs.</p>
</li>
<li><p><strong>Executor</strong> → Runs the job using Docker, Shell, Kubernetes, or another supported environment.</p>
</li>
<li><p><strong>Job</strong> → The commands defined in the <code>.gitlab-ci.yml</code> file.</p>
</li>
</ul>
<h3>☁️ Hosted Runner vs Self-Hosted Runner</h3>
<p>GitLab provides two types of runners to execute CI/CD jobs: <strong>Hosted Runners</strong> and <strong>Self-Hosted Runners</strong>.</p>
<p>The main difference is <strong>where the runner is managed</strong>.</p>
<ul>
<li><p><strong>Hosted Runners</strong> are managed by GitLab, so you don't need to install or maintain them.</p>
</li>
<li><p><strong>Self-Hosted Runners</strong> are installed and managed by you on your own infrastructure, such as a Virtual Machine, physical server, or Kubernetes cluster.</p>
</li>
</ul>
<h2>📊 Hosted Runner vs Self-Hosted Runner</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Hosted Runner</th>
<th>Self-Hosted Runner</th>
</tr>
</thead>
<tbody><tr>
<td>Managed By</td>
<td>GitLab</td>
<td>You</td>
</tr>
<tr>
<td>Setup Required</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Infrastructure</td>
<td>GitLab</td>
<td>Your Server / VM</td>
</tr>
<tr>
<td>Maintenance</td>
<td>GitLab</td>
<td>You</td>
</tr>
<tr>
<td>Custom Software</td>
<td>Limited</td>
<td>Full Control</td>
</tr>
<tr>
<td>Best For</td>
<td>Small projects &amp; beginners</td>
<td>Production &amp; enterprise projects</td>
</tr>
</tbody></table>
<h3>🚀 Hosted Runner</h3>
<p>Hosted Runners are ready to use and require no installation. GitLab automatically provisions the infrastructure needed to execute your pipeline jobs.</p>
<p>They are ideal for learning GitLab, personal projects, and small teams.</p>
<h3>🖥️ Self-Hosted Runner</h3>
<p>A Self-Hosted Runner is installed on your own machine or server. It gives you complete control over the execution environment, allowing you to install custom tools, access private networks, and optimize performance.</p>
<p>Most production environments use Self-Hosted Runners because they offer greater flexibility and security.</p>
<h3>💼 Real-World Example</h3>
<p>A startup building a portfolio website may use <strong>Hosted Runners</strong> because they're simple to set up.</p>
<p>A company deploying applications to a private Kubernetes cluster or AWS environment typically uses <strong>Self-Hosted Runners</strong> to securely access internal resources and customize the execution environment.</p>
<h3>🛠️ Registering a GitLab Runner</h3>
<p>To use a <strong>Self-Hosted Runner</strong>, you first need to register it with your GitLab project. During registration, the runner connects to GitLab and becomes available to execute pipeline jobs.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d2c0ce33-6ab6-4762-8126-269bc667e21b.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 1: Install GitLab Runner</h2>
<p>Install GitLab Runner on your Linux server by following the official installation steps for your operating system.</p>
<h2>Step 2: Get the Registration Token</h2>
<p>In your GitLab project, navigate to:</p>
<pre><code class="language-shell">Settings → CI/CD → Runners
</code></pre>
<p>Copy the <strong>Runner Authentication Token</strong> (or registration token, depending on your GitLab version).</p>
<h2>Step 3: Register the Runner</h2>
<p>Run the following command on your server:</p>
<pre><code class="language-shell">sudo gitlab-runner register
</code></pre>
<p>During registration, you'll be asked to provide:</p>
<ul>
<li><p>GitLab instance URL</p>
</li>
<li><p>Runner Authentication Token</p>
</li>
<li><p>Runner name</p>
</li>
<li><p>Executor (Docker, Shell, Kubernetes, etc.)</p>
</li>
</ul>
<p>After successful registration, the runner will appear in your project's <strong>Runners</strong> section.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e5b2d1c5-ff57-43c0-bfb7-c0d110f277d6.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e5076d84-6643-499e-b8cb-b4a2751d5fc0.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6083339b-58a1-420e-ae20-34304393ab6d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/113a3f01-1c9b-4f9c-a2ec-175faf4adba8.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e58d6daf-791f-4c45-bbae-230a2714b620.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/94ba577b-a252-4553-b614-8a2e9bf3abbd.png" alt="" style="display:block;margin:0 auto" />

<h3>🏷️ Runner Tags</h3>
<ul>
<li><p>What are Runner Tags?</p>
</li>
<li><p>Why Runner Tags are used</p>
</li>
<li><p>Assigning tags while registering a runner</p>
</li>
<li><p>Using tags in <code>.gitlab-ci.yml</code></p>
</li>
<li><p>Practical example</p>
</li>
</ul>
<pre><code class="language-yaml">build:
  tags:
    - docker
  script:
    - echo "Running on Docker Runner"
</code></pre>
<h3>📝 Pipeline Editor</h3>
<ul>
<li><p>What is Pipeline Editor?</p>
</li>
<li><p>Where to find it</p>
</li>
<li><p>Creating/editing <code>.gitlab-ci.yml</code></p>
</li>
<li><p>Validate CI/CD configuration</p>
</li>
<li><p>Commit changes directly from GitLab</p>
</li>
</ul>
<h3>⚡ Parallel Jobs</h3>
<p>Explain that multiple jobs in the same stage can run simultaneously.</p>
<pre><code class="language-yaml">stages:
  - test

unit_test:
  stage: test
  tags:
    - test
  script:
    - echo "Running Unit Tests"

integration_test:
  stage: test
  tags:
    - test
  script:
    - echo "Running Integration Tests"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/2aaa0d89-bd58-49a8-8ff1-cfed352e9ac7.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/bfbd2710-6c5d-40f1-944d-bfb66b166747.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/21e65f24-53b6-4310-8762-ee84e3e2d82c.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/dfa9dcc5-c1d9-4d71-9096-af3c4fc654b9.png" alt="" style="display:block;margin:0 auto" />

<h2>🎯 Summary</h2>
<p>Congratulations! 🎉 You have completed <strong>Day 5</strong> of the GitLab learning series.</p>
<p>In this article, you learned how GitLab Runners execute CI/CD jobs, explored Runner Architecture, compared Hosted and Self-Hosted Runners, registered your first Self-Hosted Runner, configured Runner Tags, and executed jobs in parallel.</p>
<h2><strong>👨‍💻 About the Author</strong></h2>
<p><strong>Hi, I'm Apurv Gujjar</strong>, a DevOps Engineer passionate about Cloud, AWS, Kubernetes, Docker, Terraform, GitLab, and Infrastructure Automation.</p>
<p>I share practical DevOps tutorials, real-world projects, certification guides, interview preparation, and cloud engineering best practices to help students and professionals build production-ready skills.</p>
<h2><strong>📬 Connect With Me</strong></h2>
<p>📧 <strong>Email:</strong> <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
<p>🌐 <strong>Portfolio:</strong> <a href="https://www.apurv-gujjar.co.in"><strong>https://www.apurv-gujjar.co.in</strong></a></p>
<p>🐙 <strong>GitHub:</strong> <a href="https://github.com/ApurvGujjar07"><strong>https://github.com/ApurvGujjar07</strong></a></p>
<p>💼 <strong>LinkedIn:</strong> <a href="https://www.linkedin.com/in/apurv-gujjar"><strong>https://www.linkedin.com/in/apurv-gujjar</strong></a></p>
<p>If you enjoy DevOps, Cloud, and GitLab content, feel free to connect with me. I'm always happy to share knowledge and discuss modern cloud technologies.</p>
]]></content:encoded></item><item><title><![CDATA[ Day 4  GitLab CI/CD Pipelines
]]></title><description><![CDATA[Learn Continuous Integration, Continuous Delivery, Pipelines, Stages, Jobs & .gitlab-ci.yml
📖 Introduction
In the previous articles, we explored GitLab fundamentals, repository management, and collab]]></description><link>https://apurv-gujjar.me/day-4-gitlab-ci-cd-pipelines</link><guid isPermaLink="true">https://apurv-gujjar.me/day-4-gitlab-ci-cd-pipelines</guid><category><![CDATA[GitLab]]></category><category><![CDATA[GitLab-CI]]></category><category><![CDATA[Devops]]></category><category><![CDATA[cicd]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 26 Jul 2026 08:27:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/60f90eb0-7f54-4461-af27-9a2078f7f615.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Learn Continuous Integration, Continuous Delivery, Pipelines, Stages, Jobs &amp; <code>.gitlab-ci.yml</code></p>
<h3>📖 Introduction</h3>
<p>In the previous articles, we explored GitLab fundamentals, repository management, and collaboration workflows. Now it's time to automate the software development lifecycle using <strong>GitLab CI/CD Pipelines</strong>.</p>
<p>Instead of manually building, testing, and deploying applications, GitLab can automate these tasks whenever changes are pushed to your repository. This automation helps teams deliver software faster, maintain consistent quality, and reduce human errors.</p>
<p>In this article, you'll learn the fundamentals of GitLab CI/CD, understand how pipelines work, create your first <code>.gitlab-ci.yml</code> file, and explore how GitLab executes jobs automatically from code commit to deployment.</p>
<p>By the end of this guide, you'll have a solid understanding of GitLab CI/CD and be ready to build your own automated pipelines.</p>
<h3>🎯 What You'll Learn</h3>
<p>After completing this article, you'll understand:</p>
<ul>
<li><p>✅ What is Continuous Integration (CI)?</p>
</li>
<li><p>✅ What is Continuous Delivery (CD)?</p>
</li>
<li><p>✅ What is GitLab CI/CD?</p>
</li>
<li><p>✅ What is a Pipeline?</p>
</li>
<li><p>✅ Understanding <code>.gitlab-ci.yml</code></p>
</li>
<li><p>✅ Stages</p>
</li>
<li><p>✅ Jobs</p>
</li>
<li><p>✅ Pipeline Execution Flow</p>
</li>
<li><p>✅ Build → Test → Push → Deploy Workflow</p>
</li>
<li><p>✅ Creating Your First GitLab CI/CD Pipeline</p>
</li>
</ul>
<h3>📚 Prerequisites</h3>
<p>Before continuing, make sure you have:</p>
<ul>
<li><p>A GitLab account</p>
</li>
<li><p>A GitLab repository</p>
</li>
<li><p>Git installed on your system</p>
</li>
<li><p>Basic knowledge of Git</p>
</li>
<li><p>A sample project (optional)</p>
</li>
</ul>
<h3>🚀 What is Continuous Delivery (CD)?</h3>
<p>Continuous Delivery (CD) is the practice of automatically preparing an application for deployment after it has been successfully built and tested.</p>
<p>Once the CI process completes without errors, the application is packaged and made ready for release. The final deployment to production may still require manual approval, giving teams complete control over when new features are released.</p>
<p>Continuous Delivery reduces deployment risks and ensures that software is always in a deployable state.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/12a09162-c3b0-465b-a2bf-254541af45a8.png" alt="" style="display:block;margin:0 auto" />

<h2>✅ Benefits of Continuous Delivery</h2>
<ul>
<li><p>Faster software releases</p>
</li>
<li><p>Reduced deployment risks</p>
</li>
<li><p>Consistent deployment process</p>
</li>
<li><p>Higher release confidence</p>
</li>
<li><p>Applications remain deployment-ready</p>
</li>
</ul>
<h3>🔄 What is GitLab CI/CD?</h3>
<p>GitLab CI/CD is GitLab's built-in automation platform that helps developers build, test, and deploy applications directly from their GitLab repositories.</p>
<p>Whenever code is pushed to a repository, GitLab automatically detects the <code>.gitlab-ci.yml</code> configuration file and starts a pipeline. Each pipeline consists of one or more stages, and each stage contains one or more jobs that execute predefined tasks.</p>
<p>This automation eliminates repetitive manual work, improves software quality, and accelerates the development lifecycle.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/5e4cc96b-9d02-47b3-9b39-c3d6114b4745.png" alt="" style="display:block;margin:0 auto" />

<h2>🔍 How GitLab CI/CD Works</h2>
<p>A typical GitLab CI/CD workflow follows these steps:</p>
<ol>
<li><p>A developer pushes code to a GitLab repository.</p>
</li>
<li><p>GitLab detects the <code>.gitlab-ci.yml</code> file.</p>
</li>
<li><p>A new pipeline is created automatically.</p>
</li>
<li><p>Jobs are executed stage by stage.</p>
</li>
<li><p>If all jobs succeed, the application is ready for deployment.</p>
</li>
</ol>
<p>This process runs automatically for every new commit, ensuring that code is continuously validated.</p>
<h3>⚙️ What is a Pipeline?</h3>
<p>A <strong>Pipeline</strong> is the core component of GitLab CI/CD. It is a sequence of automated steps that GitLab executes whenever changes are pushed to your repository.</p>
<p>Instead of manually building, testing, and deploying your application, a pipeline performs these tasks automatically in a predefined order.</p>
<p>A pipeline is divided into <strong>Stages</strong>, and each stage contains one or more <strong>Jobs</strong>. GitLab executes the stages one by one, ensuring that the previous stage completes successfully before moving to the next.</p>
<h3>📄 Understanding <code>.gitlab-ci.yml</code></h3>
<p>The <code>.gitlab-ci.yml</code> file is the heart of every GitLab CI/CD pipeline. It defines <strong>what should happen</strong>, <strong>when it should happen</strong>, and <strong>how GitLab should execute each job</strong>.</p>
<p>GitLab looks for this file in the <strong>root directory</strong> of your repository. Whenever a new commit is pushed, GitLab reads this configuration file and creates a pipeline based on its instructions.</p>
<p>Without a <code>.gitlab-ci.yml</code> file, GitLab has no instructions to create or execute a CI/CD pipeline.</p>
<h3>📁 Creating Your First <code>.gitlab-ci.yml</code> File</h3>
<p>Now that we understand the purpose of the <code>.gitlab-ci.yml</code> file, let's create our first GitLab CI/CD pipeline.</p>
<p>For this demonstration, I have created a simple GitLab repository named <code>gitlab-practice</code>, which we'll use throughout this article.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ef7f9aae-65b0-4971-a009-5c379c8c9b4e.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 1: Create the Configuration File</h3>
<p>Inside the root directory of your repository, create a new file named:</p>
<pre><code class="language-shell">.gitlab-ci.yml
</code></pre>
<p>GitLab automatically detects this file whenever new changes are pushed to the repository.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/af176755-74c0-4af5-b209-f4b7ea18db36.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>Step 2: Add Your First Pipeline</strong></h3>
<p>Open the .gitlab-ci.yml file and add the following configuration:</p>
<pre><code class="language-yaml">stages:
  - build

build_job:
  stage: build
  script:
    - echo "Hello from GitLab CI/CD!"
    - echo "Building the application..."
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e6d482d1-2724-42d2-b6e0-6f49314a8247.png" alt="" style="display:block;margin:0 auto" />

<p>This is the simplest GitLab CI/CD pipeline.</p>
<p>Let's understand what each section does.</p>
<h3>Understanding the Configuration</h3>
<pre><code class="language-shell">stages:
  - build
</code></pre>
<p>Here, we define a single stage named <strong>build</strong>.</p>
<p>A stage represents a phase of the pipeline. Every job assigned to this stage will execute when the pipeline runs.</p>
<pre><code class="language-yaml">build_job:
</code></pre>
<p>This is the name of our first job.</p>
<p>You can choose any meaningful name, such as:</p>
<pre><code class="language-yaml">build_app
compile_code
docker_build
</code></pre>
<p>The job name is only used to identify the task inside the pipeline.</p>
<pre><code class="language-yaml">stage: build
</code></pre>
<p>This tells GitLab that the job belongs to the <strong>build</strong> stage.</p>
<p>If multiple stages exist, GitLab executes them in the order they are defined.</p>
<pre><code class="language-yaml">script:
</code></pre>
<p>The <code>script</code> section contains the commands that GitLab Runner will execute.</p>
<p>In our example, it simply prints two messages to the job logs.</p>
<p>script:</p>
<pre><code class="language-yaml">echo "Hello from GitLab CI/CD!"


echo "Building the application..."
</code></pre>
<p>When the pipeline runs, the output will look similar to:</p>
<pre><code class="language-plaintext">Hello from GitLab CI/CD!
Building the application...
</code></pre>
<h3>Step 3: Commit and Push the Changes</h3>
<p>After creating the <code>.gitlab-ci.yml</code> file, commit and push it to your GitLab repository.</p>
<pre><code class="language-shell">git add .
git commit -m "Add first GitLab CI/CD pipeline"
git push origin main
</code></pre>
<p>As soon as the code is pushed, GitLab automatically starts a new pipeline.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ede38c4b-9454-403b-9bfb-7e0955fd5e2b.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1c1cf1b9-f593-48a7-b9fe-dd327fdefbf4.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>🚀 Step 4: Watch Your First Pipeline in Action</strong></h3>
<p>After committing and pushing the <code>.gitlab-ci.yml</code> file, GitLab automatically detects the new configuration and creates a pipeline.</p>
<p>You don't need to start the pipeline manually. As soon as the changes are pushed to the repository, GitLab begins executing the pipeline based on the instructions defined in the <code>.gitlab-ci.yml</code> file.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/fadf10f1-b0e5-46de-90a5-9d75e4457ef0.png" alt="" style="display:block;margin:0 auto" />

<h3>🔍 Viewing Job Logs</h3>
<p>Click on the pipeline, then select the <strong>build_job</strong>.</p>
<p>GitLab opens the job details page where you can see the complete execution log generated by the Runner.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/28a5c087-c506-4e23-a5f6-ac3daeca5e72.png" alt="" style="display:block;margin:0 auto" />

<h3>🏗️ Understanding Stages</h3>
<p>In our first pipeline, we created only one stage called <strong>build</strong>.</p>
<p>A <strong>Stage</strong> represents a phase of the CI/CD pipeline. GitLab executes stages sequentially, meaning the next stage starts only after the previous one completes successfully.</p>
<p>In real-world projects, pipelines usually contain multiple stages such as building the application, running tests, and deploying it.</p>
<p>For example:</p>
<p>stages:</p>
<pre><code class="language-shell">build
test
deploy
</code></pre>
<p>This tells GitLab to execute the pipeline in the following order:</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/94dae497-6646-42f5-b77c-226879e2511b.png" alt="" style="display:block;margin:0 auto" />

<h3>⚙️ Understanding Jobs</h3>
<p>A Job is an individual task that runs inside a stage.</p>
<p>Every job performs a specific action, such as building the application, running tests, or deploying code.</p>
<p>In our example, the job is named build_job.</p>
<pre><code class="language-yaml">build_job:
  stage: build
  script:
    - echo "Hello from GitLab CI/CD!"
    - echo "Building the application..."
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>build_job</code> → Name of the job</p>
</li>
<li><p><code>stage: build</code> → Assigns the job to the build stage</p>
</li>
<li><p><code>script</code> → Commands executed by the GitLab Runner</p>
</li>
</ul>
<p>When the pipeline runs, GitLab executes the commands listed under the <code>script</code> section.</p>
<h3>🧩 Multiple Jobs in a Stage</h3>
<p>A stage can contain more than one job.</p>
<pre><code class="language-yaml">stages:
  - build

build_app:
  stage: build
  script:
    - echo "Building Application"

build_docker:
  stage: build
  script:
    - echo "Building Docker Image"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/046abb38-b684-457e-bc73-e0159da4a4c9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1ee66e4b-6ea8-4371-a353-7f1f522322b6.png" alt="" style="display:block;margin:0 auto" />

<h3>🔄 Build → Test → Push → Deploy Workflow</h3>
<p>A typical GitLab CI/CD pipeline follows four key stages. First, the application is <strong>built</strong> by compiling the code, installing dependencies, or creating a Docker image. Next, automated <strong>tests</strong> verify that the application works correctly. If all tests pass, the Docker image or build artifact is <strong>pushed</strong> to a container registry. Finally, the application is <strong>deployed</strong> to the target environment, such as a Virtual Machine, Kubernetes cluster, or cloud platform.</p>
<pre><code class="language-yaml">stages:
  - build
  - test
  - push
  - deploy

build:
  stage: build
  script:
    - echo "Building the application..."

test:
  stage: test
  script:
    - echo "Running tests..."

push:
  stage: push
  script:
    - echo "Pushing Docker image..."

deploy:
  stage: deploy
  script:
    - echo "Deploying application..."
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/cdd512e5-212f-431c-a82d-23b5e8d11aea.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/bc5c4aba-84e0-4b6a-82ea-0b8704a41b1d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d6b3d538-c0b9-4664-bf1f-9c3c61c1dc1d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/53557000-5906-4cd9-a06e-5ff76c9820df.png" alt="" style="display:block;margin:0 auto" />

<h3>🎯 Summary</h3>
<p>Congratulations! 🎉 You have completed <strong>Day 4</strong> of the GitLab learning series.</p>
<p>In this article, you learned <strong>GitLab CI/CD</strong>, created your first <code>.gitlab-ci.yml</code> file, understood <strong>pipelines, stages, and jobs</strong>, and explored the <strong>Build → Test → Push → Deploy</strong> workflow.</p>
<h2><strong>👨‍💻 About the Author</strong></h2>
<p><strong>Hi, I'm Apurv Gujjar</strong>, a DevOps Engineer passionate about Cloud, AWS, Kubernetes, Docker, Terraform, GitLab, and Infrastructure Automation.</p>
<p>I share practical DevOps tutorials, real-world projects, certification guides, interview preparation, and cloud engineering best practices to help students and professionals build production-ready skills.</p>
<h2><strong>📬 Connect With Me</strong></h2>
<p>📧 <strong>Email:</strong> <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
<p>🌐 <strong>Portfolio:</strong> <a href="https://www.apurv-gujjar.co.in"><strong>https://www.apurv-gujjar.co.in</strong></a></p>
<p>🐙 <strong>GitHub:</strong> <a href="https://github.com/ApurvGujjar07"><strong>https://github.com/ApurvGujjar07</strong></a></p>
<p>💼 <strong>LinkedIn:</strong> <a href="https://www.linkedin.com/in/apurv-gujjar"><strong>https://www.linkedin.com/in/apurv-gujjar</strong></a></p>
<p>If you enjoy DevOps, Cloud, and GitLab content, feel free to connect with me. I'm always happy to share knowledge and discuss modern cloud technologies.</p>
]]></content:encoded></item><item><title><![CDATA[Docker Scout, Hardened Images, AI & Supply Chain Security]]></title><description><![CDATA[Learn Docker Scout, Multi-Stage Builds, Docker Hardened Images (DHI), SBOM, Docker Model Runner, Ask Gordon AI, and production-ready container security through practical, real-world examples.
Introduc]]></description><link>https://apurv-gujjar.me/docker-with-ai-security</link><guid isPermaLink="true">https://apurv-gujjar.me/docker-with-ai-security</guid><category><![CDATA[Docker]]></category><category><![CDATA[docker scout]]></category><category><![CDATA[Security]]></category><category><![CDATA[sbom]]></category><category><![CDATA[debugging]]></category><category><![CDATA[Ask Gordon AI]]></category><category><![CDATA[docker model runner]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Wed, 22 Jul 2026 17:21:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c76f7945-efc5-4fc0-a168-7551497d9eb6.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Learn Docker Scout, Multi-Stage Builds, Docker Hardened Images (DHI), SBOM, Docker Model Runner, Ask Gordon AI, and production-ready container security through practical, real-world examples.</strong></p>
<h2>Introduction</h2>
<p>Docker has become the standard for building and deploying modern applications, but creating a container image is only the beginning. Every image includes operating system packages and application dependencies that may contain known vulnerabilities (CVEs), making container security a critical part of the software delivery lifecycle.</p>
<p>Modern DevOps teams don't just build containers—they scan, optimize, harden, and continuously improve them before deployment.</p>
<p>In this hands-on guide, you'll learn how to secure Docker images using <strong>Docker Scout</strong>, reduce image size with <strong>Multi-Stage Builds</strong>, generate <strong>SBOMs</strong>, build secure applications with <strong>Docker Hardened Images</strong>, run local AI models using <strong>Docker Model Runner</strong>, and troubleshoot Docker projects with <strong>Ask Gordon AI</strong>.</p>
<p>By the end of this tutorial, you'll have a practical understanding of building lightweight, secure, and production-ready Docker containers using modern Docker features.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e167c3d6-7b1e-4b34-b493-ce0d0fc0e6ff.png" alt="" style="display:block;margin:0 auto" />

<h2>What You'll Learn</h2>
<p>After completing this guide, you'll be able to:</p>
<ul>
<li><p>Understand modern Docker security concepts.</p>
</li>
<li><p>Scan images using Docker Scout.</p>
</li>
<li><p>Analyze and prioritize CVEs.</p>
</li>
<li><p>Generate Software Bill of Materials (SBOM).</p>
</li>
<li><p>Build optimized images using Multi-Stage Builds.</p>
</li>
<li><p>Secure containers with Docker Hardened Images (DHI).</p>
</li>
<li><p>Debug containers without a shell.</p>
</li>
<li><p>Apply production-ready container hardening techniques.</p>
</li>
<li><p>Run local AI models using Docker Model Runner.</p>
</li>
<li><p>Troubleshoot Docker projects with Ask Gordon AI.</p>
</li>
<li><p>Follow Docker security best practices used in production.</p>
</li>
</ul>
<h2>Why Read This Guide?</h2>
<p>Most Docker tutorials end after building an image. In production, that's where the real work begins.</p>
<p>Before deploying a container, every DevOps engineer should be able to answer questions like:</p>
<ul>
<li><p>Is the image vulnerable?</p>
</li>
<li><p>Can the image be made smaller and more secure?</p>
</li>
<li><p>Are secrets accidentally included?</p>
</li>
<li><p>Is the container running as a non-root user?</p>
</li>
<li><p>Can we generate an SBOM for compliance?</p>
</li>
<li><p>How can AI simplify Docker development?</p>
</li>
</ul>
<p>This guide answers all of these questions through practical examples, real-world scenarios, and production best practices.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/33ecf514-5553-440a-adb7-5923215ccb90.png" alt="" style="display:block;margin:0 auto" />

<h2>Prerequisites</h2>
<p>You'll need:</p>
<ul>
<li><p>Docker Desktop (latest version)</p>
</li>
<li><p>Docker CLI</p>
</li>
<li><p>Docker Hub account</p>
</li>
<li><p>Basic Docker knowledge</p>
</li>
<li><p>Familiarity with Dockerfiles</p>
</li>
<li><p>Any sample application for practice</p>
</li>
</ul>
<p>The concepts demonstrated in this guide apply to any Dockerized application, regardless of the programming language or framework.</p>
<h2><code>Part 1 — Docker Scout</code></h2>
<h2>What is Docker Scout?</h2>
<p>Building a Docker image is easy, but knowing whether it's secure is a completely different challenge.</p>
<p>A typical Docker image contains hundreds of operating system packages, libraries, and application dependencies. While these components make your application work, they can also introduce known security vulnerabilities (CVEs). Deploying an image without checking its security posture can expose your application to unnecessary risks.</p>
<p>This is where <strong>Docker Scout</strong> comes in.</p>
<p>Docker Scout is Docker's built-in security analysis tool that scans container images for known vulnerabilities, identifies outdated packages, recommends more secure base images, and helps developers improve the overall security of their containers before deployment.</p>
<p>Instead of waiting until production to discover security issues, Docker Scout allows you to identify and fix vulnerabilities early in the development lifecycle.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0853466a-9258-4c41-8b17-fd39c109435b.png" alt="" style="display:block;margin:0 auto" />

<h2>Why Should You Scan Docker Images?</h2>
<p>Imagine you've built a Docker image using an older Ubuntu or Node.js base image. Even if your application code is perfectly secure, the base image itself may contain dozens of publicly disclosed vulnerabilities.</p>
<p>Without scanning, these issues remain hidden until they are exploited or discovered during a security audit.</p>
<p>Docker Scout helps answer important questions such as:</p>
<ul>
<li><p>Does my image contain known CVEs?</p>
</li>
<li><p>Which vulnerabilities are the most critical?</p>
</li>
<li><p>Are fixes available?</p>
</li>
<li><p>Can Docker recommend a more secure base image?</p>
</li>
<li><p>Which packages are responsible for these vulnerabilities?</p>
</li>
</ul>
<p>This allows developers to make informed security decisions before releasing an application.</p>
<h3><code>Hands-on Lab — Scan Your First Docker Image</code></h3>
<p>Now it's time to perform our first security scan using Docker Scout.</p>
<p>We'll build a sample Docker image and analyze it for vulnerabilities.</p>
<h2>Step 1 — Clone the Sample Application</h2>
<p>We'll use a sample application throughout this guide.</p>
<p>Run the following command:</p>
<pre><code class="language-shell">git clone https://github.com/LondheShubham153/devboard.git
</code></pre>
<p>Once the repository is cloned, navigate into the project directory.</p>
<pre><code class="language-shell">cd devboard
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ee27ad03-9f4d-4f0e-a054-d8a649ff453c.png" alt="" style="display:block;margin:0 auto" />

<p>Verify the project files.</p>
<pre><code class="language-shell">ls
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/17bc9678-25b0-480e-9b7c-cb2936fbf2aa.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 2 — Build the Docker Image</h2>
<p>Now let's build the Docker image.</p>
<p>Replace the image name with your preferred name.</p>
<p>Example:</p>
<pre><code class="language-shell">docker build -t docker-security-demo:v1 .
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f240d4d6-6dcb-4419-99f4-4fd23d9f780f.png" alt="" style="display:block;margin:0 auto" />

<p>Docker will begin downloading the required base image, installing dependencies, and building the final image.</p>
<p>Depending on your internet speed, this may take a few minutes during the first build.</p>
<h2>Step 3 — Verify the Image</h2>
<p>Before scanning, confirm that Docker created the image successfully.</p>
<p>Run:</p>
<pre><code class="language-shell">docker images
</code></pre>
<p>You should see your newly created image in the list.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/7225fa69-ed14-4717-aaa9-6f7983000996.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6b777f9b-76dc-45e0-a5b3-07e2e6c68f7e.png" alt="" style="display:block;margin:0 auto" />

<h3><code>Scan Your First Docker Image with Docker Scout</code></h3>
<p>Now that our Docker image has been built successfully, it's time to analyze its security posture.</p>
<p>Building an image doesn't guarantee that it's secure. Every image inherits packages and dependencies from its base image, and those packages may contain publicly disclosed vulnerabilities.</p>
<p>Docker Scout helps us identify these vulnerabilities before the image reaches production.</p>
<p>In this section, we'll perform our first vulnerability scan and learn how to interpret the security report generated by Docker Scout.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/46a2213e-9bea-450b-b683-a1b859ae5160.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 4 — Perform Your First Docker Scout Scan</h3>
<p>Docker Scout provides a quick security summary using the <code>quickview</code> command.</p>
<p>Run the following command:</p>
<pre><code class="language-shell">docker scout quickview local://docker-security-demo:v1
</code></pre>
<blockquote>
<p>Replace <code>docker-security-demo:v1</code> with your own image name if you're using a different tag.</p>
</blockquote>
<p>Docker Scout will analyze the image locally and display a summary of the detected vulnerabilities.</p>
<p>Unlike a detailed CVE report, <strong>QuickView</strong> focuses on giving you an overview of the image's security posture in just a few seconds.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1d7a8e60-d528-414f-9cbb-201928b2037f.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1c65e7a8-5a06-4a96-8e80-0ce51a6dd368.png" alt="" style="display:block;margin:0 auto" />

<h3>Up Next → Detailed CVE Analysis</h3>
<p>In the next section, we'll use:</p>
<pre><code class="language-shell">docker scout cves local://docker-security-demo:v1
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6674d11c-0ea1-4f8f-9101-3da3b15bd0a6.png" alt="" style="display:block;margin:0 auto" />

<p>This command provides a detailed vulnerability report, including:</p>
<ul>
<li><p>The affected package</p>
</li>
<li><p>CVE ID</p>
</li>
<li><p>Severity level</p>
</li>
<li><p>Installed version</p>
</li>
<li><p>Fixed version (if available)</p>
</li>
<li><p>Recommended remediation steps</p>
</li>
</ul>
<p>We'll learn how to read a real CVE report like a security engineer and identify which vulnerabilities actually require immediate attention.</p>
<p><code>Part 2 — Analyze Vulnerabilities with Docker Scout CVE Reports</code></p>
<p>QuickView gives you a high-level overview of your image's security posture, but security engineers don't make decisions based on summary reports alone.</p>
<p>To understand exactly <strong>which packages are vulnerable, how severe the vulnerabilities are, and whether fixes are available</strong>, we need a detailed CVE report.</p>
<p>Docker Scout provides this information through the <code>cves</code> command, making it easier to identify the components that require immediate attention.</p>
<p>In this section, we'll generate a complete vulnerability report and learn how to interpret it like a DevSecOps engineer.</p>
<h3>Step 5 — Generate a Detailed CVE Report</h3>
<p>Run the following command:</p>
<pre><code class="language-shell">docker scout cves local://docker-security-demo:v1
</code></pre>
<blockquote>
<p>Replace <code>docker-security-demo:v1</code> with your own image name if you're using a different image.</p>
</blockquote>
<p>Docker Scout will scan every package inside your container image and display a detailed list of detected vulnerabilities.</p>
<p>Unlike <code>quickview</code>, this report shows <strong>exactly where each vulnerability exists and whether an update is available.</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/dc3a8ebe-4816-477f-8d3c-a193e7c6e24f.png" alt="" style="display:block;margin:0 auto" />

<h3>What is a CVE?</h3>
<p>A <strong>Common Vulnerabilities and Exposures (CVE)</strong> is a globally recognized identifier assigned to publicly disclosed security vulnerabilities.</p>
<p>Each CVE has its own unique ID, making it easy for developers, vendors, and security teams to discuss the same vulnerability without confusion.</p>
<p>For example:</p>
<pre><code class="language-plaintext">CVE-2025-12345
</code></pre>
<p>A CVE record typically includes:</p>
<ul>
<li><p>Vulnerability description</p>
</li>
<li><p>Affected software versions</p>
</li>
<li><p>Severity score</p>
</li>
<li><p>References</p>
</li>
<li><p>Available fixes</p>
</li>
</ul>
<p>Think of a CVE as a <strong>tracking number</strong> for a known security issue.</p>
<h3>💡 Pro Tip</h3>
<p>Don't rush to fix every vulnerability immediately.</p>
<p>Instead, focus on vulnerabilities that:</p>
<ul>
<li><p>Have an available fix.</p>
</li>
<li><p>Affect packages exposed to external users.</p>
</li>
<li><p>Are marked as <strong>Critical</strong> or <strong>High</strong> severity.</p>
</li>
<li><p>Exist in your runtime image rather than build-only dependencies.</p>
</li>
</ul>
<p>This approach helps you prioritize security work more effectively.</p>
<h3>⚠️ Common Mistake</h3>
<p>Many beginners assume that every reported CVE is equally dangerous.</p>
<p>In reality, vulnerability scanners report the <strong>presence</strong> of a vulnerable package—not necessarily that the vulnerability is exploitable in your application.</p>
<p>For example, a package used only during the build process poses much less risk than a vulnerable web server library exposed to incoming user requests.</p>
<p>Always evaluate vulnerabilities in the context of your application before deciding on remediation.</p>
<h3>Prioritize Vulnerabilities with Docker Scout</h3>
<p>Finding vulnerabilities is only the first step. In real-world environments, security teams don't fix every CVE immediately. Instead, they prioritize vulnerabilities based on <strong>severity, fix availability, and business impact</strong>.</p>
<p>Docker Scout makes this easier by highlighting which vulnerabilities are actionable.</p>
<h2>Step 6 — Show Only Fixable Vulnerabilities</h2>
<p>Instead of reviewing hundreds of CVEs manually, filter the report to display only vulnerabilities that already have an available fix.</p>
<p>Run:</p>
<pre><code class="language-shell">docker scout cves local://docker-security-demo:v1 --only-fixed
</code></pre>
<p>This reduces noise and helps you focus on vulnerabilities that can actually be remediated.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ef583f0d-d5ec-470a-b38c-7183a3a9e88d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1b40ed73-6911-4a74-b88b-3aeeed8beb9c.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 7 — Filter High and Critical Vulnerabilities</h3>
<p>Production teams usually prioritize Critical and High severity issues first.</p>
<p>Run:</p>
<pre><code class="language-shell">docker scout cves local://docker-security-demo:v1 --only-severity critical,high
</code></pre>
<p>This filters the report and displays only the vulnerabilities that require immediate attention.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f1a7a6f5-5fbc-40bb-8584-86c47f0ecf4d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d42ba1c7-f422-48cf-83e8-bd27683f7371.png" alt="" style="display:block;margin:0 auto" />

<h2>Best Practices</h2>
<ul>
<li><p>Prioritize <strong>Critical</strong> and <strong>High</strong> vulnerabilities.</p>
</li>
<li><p>Fix vulnerabilities with available patches first.</p>
</li>
<li><p>Update the base image regularly.</p>
</li>
<li><p>Re-scan the image after every major dependency update.</p>
</li>
</ul>
<h3><code>Up Next → Compare Your Base Image with Recommended Alternatives</code></h3>
<p>In the next section, we'll use Docker Scout's <strong>recommend</strong> feature to:</p>
<ul>
<li><p>Check whether a newer base image is available.</p>
</li>
<li><p>Compare your current base image with recommended alternatives.</p>
</li>
<li><p>Reduce vulnerabilities by simply changing the <code>FROM</code> image.</p>
</li>
<li><p>Understand Docker Scout's remediation recommendations.</p>
</li>
</ul>
<h3><code>Part 3 Find a Better Base Image with Docker Scout</code></h3>
<p>After identifying vulnerabilities, the next step is to check whether Docker Scout recommends a more secure base image.</p>
<p>In many cases, simply updating the base image can significantly reduce the number of vulnerabilities without changing your application code.</p>
<h3>Step 8 — View Base Image Recommendations</h3>
<p>Run the following command:</p>
<pre><code class="language-shell">docker scout recommendations local://docker-security-demo:v1
</code></pre>
<blockquote>
<p>Replace <code>docker-security-demo:v1</code> with your image name if required.</p>
</blockquote>
<p>Docker Scout analyzes your current base image and suggests newer or more secure alternatives.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c246cf68-9a54-49a4-baf3-74cdc334921e.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/60d39336-c6cc-4360-a0b2-32f39730cce1.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/cfbb5355-9cfc-4b1e-8dcc-036eb79afa63.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/097ba858-1e95-4a22-927c-bb54b6366879.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 9 — Update the Base Image</h3>
<p>Open your <code>Dockerfile</code> and replace the existing base image with the recommended version.</p>
<p>Example:</p>
<p><strong>Before</strong></p>
<pre><code class="language-shell">FROM node:22-alpine
</code></pre>
<p><strong>After</strong></p>
<pre><code class="language-shell">FROM node:24-alpine
</code></pre>
<blockquote>
<p>Your recommended version may be different depending on Docker Scout's output.</p>
</blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/45b11b92-2190-4d41-8bd5-fbc790222ea5.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 10 — Rebuild the Image</h3>
<p>After updating the Dockerfile, rebuild the image.</p>
<pre><code class="language-shell">docker build -t docker-security-demo:v2 .
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/4de9934f-a7c8-4904-8cd8-93e0816b3edb.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c27cf200-685a-4060-ba98-e2d079d3f76e.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 11 — Scan the Updated Image</h3>
<p>Run QuickView again to compare the results.</p>
<pre><code class="language-shell">docker scout quickview local://docker-security-demo:v2
</code></pre>
<p>Compare the vulnerability count with the previous scan.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/2ee52b98-c432-4bc4-84ad-72a1921998a3.png" alt="" style="display:block;margin:0 auto" />

<h3>💡 Best Practice</h3>
<p>Always use the latest stable and officially supported base image, then re-scan after every upgrade.</p>
<h3>Part 4 — Generate an SBOM with Docker Scout</h3>
<p>An SBOM (Software Bill of Materials) provides a complete inventory of all packages, libraries, and dependencies included in your container image. It's widely used for security audits, compliance, and software supply chain visibility.</p>
<h3>Step 12 — Generate an SBOM</h3>
<p>Run the following command:</p>
<pre><code class="language-shell">docker scout sbom local://docker-security-demo:v2
</code></pre>
<p>Docker Scout will generate an SBOM and list all the packages included in your image.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b414b8cf-8a29-44db-82e4-338c74fdde0d.png" alt="" style="display:block;margin:0 auto" />

<p>output is too large that's why i mention only two snap's for your reference .</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b5a18071-f627-4ced-930e-2e61532554a3.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9bdf7c47-0ead-4f71-8113-b7ef89a4ea16.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 13 — Export the SBOM</h3>
<p>Instead of displaying it in the terminal, save it as a JSON file.</p>
<pre><code class="language-shell">docker scout sbom local://docker-security-demo:v2 --format spdx-json &gt; sbom.json
</code></pre>
<p>This creates an <code>sbom.json</code> file in your current directory.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/47fa34a4-75d6-44e2-8924-170d552de8cb.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 14 — Verify the SBOM File</h3>
<p>Windows PowerShell:</p>
<pre><code class="language-shell">cat sbom.json
</code></pre>
<p>You'll see package metadata in JSON format.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/224d8bb0-8526-456f-8cf3-d44bb8e5b704.png" alt="" style="display:block;margin:0 auto" />

<h3>💡 Best Practice</h3>
<p>Generate a fresh SBOM every time you release a new application version. It helps track dependencies, simplifies security audits, and improves software supply chain transparency.</p>
<h3><code>Part 5 — Optimize Images with Multi-Stage Builds</code></h3>
<p>A standard Docker image often includes build tools, source code, and temporary files that aren't needed at runtime. Multi-Stage Builds help create smaller, cleaner, and more secure production images by keeping only the required application files.</p>
<h3>Step 15 — Build Using the Existing Dockerfile</h3>
<p>First, build the application using the standard Dockerfile.</p>
<pre><code class="language-shell">docker build -f Dockerfile -t docker-standard:v1 .
</code></pre>
<p>Check the image size.</p>
<pre><code class="language-shell">docker images
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/cb57e21e-5bfe-49f5-a8ed-53ce05e2be1b.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 16 — Build Using the Multi-Stage Dockerfile</h3>
<p>The project already contains a <code>Dockerfile.multistage</code>.</p>
<p>Build the image using it.</p>
<pre><code class="language-shell">docker build -f Dockerfile.multistage -t docker-multistage:v1 .
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/67a12228-7a8c-473f-b61d-8694d9a7b78d.png" alt="" style="display:block;margin:0 auto" />

<p>After the build completes, verify the image size.</p>
<pre><code class="language-shell">docker images
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/cc51e919-cf8c-44aa-8c32-c7154ffd38e9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/aa504208-03a7-4559-b74b-bd42eeb118aa.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 17 — Compare the Image Sizes</h3>
<p>Run:</p>
<pre><code class="language-shell">docker images
</code></pre>
<p>Compare both images.</p>
<table>
<thead>
<tr>
<th>Image</th>
<th>Expected Result</th>
</tr>
</thead>
<tbody><tr>
<td>Standard Build</td>
<td>Larger image</td>
</tr>
<tr>
<td>Multi-Stage Build</td>
<td>Smaller image</td>
</tr>
</tbody></table>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/35f29bb3-4e90-4718-8cdb-c539930d237c.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 18 — Verify the Application</h3>
<h3>Run the Multi-Stage image.</h3>
<pre><code class="language-shell">docker run -d -p 3000:4173 --name multistage-demo docker-multistage:v1
</code></pre>
<p>Verify it's running.</p>
<pre><code class="language-shell">docker ps
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1351dfc1-f5fd-4cc5-a766-5fe0aadbff0c.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a9a81886-6471-4a40-b424-6d6aeadefdb6.png" alt="" style="display:block;margin:0 auto" />

<p>Open the application:</p>
<pre><code class="language-shell">http://localhost:3000
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c0ead532-4bb9-4431-bc75-8f5382ca992a.png" alt="" style="display:block;margin:0 auto" />

<h3>Part 6 — Optimize Build Context with <code>.dockerignore</code></h3>
<p>Even with Multi-Stage Builds, Docker may still send unnecessary files during the build process. A <code>.dockerignore</code> file excludes files that aren't required during the image build, resulting in faster builds, smaller build contexts, and preventing sensitive files from being included accidentally.</p>
<h3>Step 19 — Check the Current Build Context</h3>
<p>Build the image once without changing anything.</p>
<pre><code class="language-shell">docker build -t docker-context:v1 .
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/626a774d-443c-4991-b45f-85c194e5f87d.png" alt="" style="display:block;margin:0 auto" />

<p>During the build, notice the following line:</p>
<pre><code class="language-shell">transferring context: XX MB
</code></pre>
<p>This shows the size of the build context sent to the Docker daemon.</p>
<h3>Step 20 — Create a <code>.dockerignore</code> File</h3>
<h3>Create a new file named:</h3>
<pre><code class="language-shell">.dockerignore
</code></pre>
<p>Add the following entries:</p>
<pre><code class="language-shell">node_modules
.git
.gitignore
README.md
Dockerfile*
.vscode
.env
.env.*
dist
coverage
</code></pre>
<p>Adjust this list based on your project if needed.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/92386a7c-9adf-4d5a-bd4d-6c9c76f6e908.png" alt="" style="display:block;margin:0 auto" />

<h2>Best Practices</h2>
<ul>
<li><p>Always include a <code>.dockerignore</code> file in every Docker project.</p>
</li>
<li><p>Never include <code>.env</code> files or secrets in the build context.</p>
</li>
<li><p>Exclude <code>node_modules</code>, <code>.git</code>, logs, cache, and IDE files.</p>
</li>
<li><p>Review the build context after major project changes.</p>
</li>
</ul>
<h3><code>Part 7 — Secure Your Containers with Docker Hardened Images (DHI)</code></h3>
<p>Docker Hardened Images (DHI) are production-ready base images designed to reduce the attack surface by including only the components required to run your application.</p>
<p>In this section, we'll pull a hardened image, compare it with a standard image, and analyze its security using Docker Scout.</p>
<h3>Step 23 — View Available Docker Hardened Images</h3>
<p>Open Docker Hub and navigate to the Docker Hardened Images catalog.</p>
<p>👉 <strong>Official Docker Hardened Images Catalog</strong></p>
<p><a href="https://hub.docker.com/catalogs/docker-hardened-images">https://hub.docker.com/catalogs/docker-hardened-images</a></p>
<p>Browse the available images and select the runtime that matches your application (Node.js, Python, Java, Go, .NET, etc.).</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/2eb95b26-1a0a-47e3-8212-e6054af67bf9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d6b7e949-7602-4bbd-99d5-440c9991ec0e.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 24 — Pull a Hardened Image</h3>
<p>Pull the Node.js Hardened Image.</p>
<pre><code class="language-shell">docker pull dhi.io/node:22
</code></pre>
<blockquote>
<p>Replace the image with the runtime you want to test.</p>
</blockquote>
<p>After the download completes, verify the image.</p>
<pre><code class="language-shell">docker images
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b64a3e9d-1bdc-41cd-81d5-09bbce5b8229.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/3340a453-d552-4679-8cc5-11474ea67465.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/18f23173-2359-4971-905d-6cc23309f5d7.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 25 — Scan the Hardened Image</h3>
<p>Run Docker Scout against the hardened image.</p>
<pre><code class="language-shell">docker scout quickview dhi.io/node:22
</code></pre>
<p>Review the vulnerability summary and compare it with the standard Node image scanned earlier.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6a5e1c06-6fbf-4427-a9d8-123e9763486d.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 26 — Compare Standard vs Hardened Image</h3>
<p>Compare the results from both images.</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Standard Image</th>
<th>Docker Hardened Image</th>
</tr>
</thead>
<tbody><tr>
<td>Vulnerabilities</td>
<td>Higher</td>
<td>Lower</td>
</tr>
<tr>
<td>Installed Packages</td>
<td>More</td>
<td>Minimal</td>
</tr>
<tr>
<td>Attack Surface</td>
<td>Larger</td>
<td>Smaller</td>
</tr>
<tr>
<td>Production Ready</td>
<td>Standard</td>
<td>Security Optimized</td>
</tr>
</tbody></table>
<h3>✅ Best Practices</h3>
<ul>
<li><p>Use Docker Hardened Images for production workloads.</p>
</li>
<li><p>Keep the image updated regularly.</p>
</li>
<li><p>Re-scan after every version upgrade.</p>
</li>
<li><p>Combine Hardened Images with Multi-Stage Builds for maximum security.</p>
</li>
</ul>
<h3><code>Part 8 — Debug Docker Hardened Images with Docker Debug</code></h3>
<p>Docker Hardened Images intentionally remove shells and debugging tools to reduce the attack surface. Instead of modifying the container, Docker provides <strong>Docker Debug</strong>, which lets you troubleshoot running containers without permanently changing them.</p>
<h3>Step 27 — Verify Docker Debug</h3>
<p>First, check whether Docker Debug is available.</p>
<pre><code class="language-shell">docker debug --help
</code></pre>
<p>If Docker Debug is installed correctly, you'll see the available commands and options.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9a1de51e-41b9-4b80-b0c3-1e4d6df09faf.png" alt="" style="display:block;margin:0 auto" />

<h3><code>Part 9 — Run Local AI Models with Docker Model Runner</code></h3>
<p>Docker Model Runner allows you to download and run AI models locally using Docker Desktop. The models run entirely on your machine, making it easy to experiment with AI without relying on external APIs.</p>
<h3>Step 28 — Verify Docker Model Runner</h3>
<p>First, check whether Docker Model Runner is available.</p>
<pre><code class="language-shell">docker model --help
</code></pre>
<p>If Docker Model Runner is enabled, Docker will display the available model management commands.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b4915ce1-5471-40c1-9433-d8b83d9503ef.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/13072ab8-a165-47f0-b2f0-94328d2486db.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 29 — List Available Models</h3>
<p>Run:</p>
<pre><code class="language-shell">docker model ls
</code></pre>
<p>This displays all AI models currently available on your system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/91392006-10ce-4f04-b56d-5493076aba10.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 30 — Pull Your First AI Model</h3>
<p>Download a model from the Docker Model Registry.</p>
<p>Run:</p>
<pre><code class="language-shell">docker model pull ai/smollm2
</code></pre>
<p>Docker will download the model and store it locally.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f431aab9-7e25-40a4-84ee-0522bef5c145.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 31 — Verify the Downloaded Model</h3>
<p>List the locally available models.</p>
<pre><code class="language-shell">docker model ls
</code></pre>
<p>You should see the newly downloaded model.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c4e93ba0-bd23-44da-bc18-6dde2b3e6cc9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/4c3624aa-4158-4031-9d12-fffc86fcb4dc.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 32 — Run the AI Model</h3>
<p>Start an interactive session with the downloaded model.</p>
<pre><code class="language-shell">docker model run ai/smollm2
</code></pre>
<p>The model will start locally and wait for your prompt.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c765bf12-32db-487b-beee-5afc7c0e0b61.png" alt="" style="display:block;margin:0 auto" />

<h3><code>Part 10 — Troubleshoot Docker Projects with Ask Gordon AI</code></h3>
<p>Ask Gordon AI is Docker's built-in AI assistant that helps you understand Docker commands, explain errors, optimize Dockerfiles, and troubleshoot Docker projects directly from Docker Desktop.</p>
<h3>Step 34 — Open Ask Gordon AI</h3>
<p>Open <strong>Docker Desktop</strong> and navigate to the <strong>Ask Gordon</strong> section from the left sidebar.</p>
<p>Wait for the AI assistant to load.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/5928769d-4e26-4b59-95fa-02a5fb86e35f.png" alt="" style="display:block;margin:0 auto" />

<p>or if you want to run on your terminal then you can run the below command :-</p>
<pre><code class="language-shell">docker ai
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/807bcdf6-db64-4186-b718-48c91bdef2c8.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/33ceb3dd-08c5-4445-9900-5bce1cd10f04.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1541fb16-019d-4f38-b0d1-87a9c5104787.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/8d68ab0c-9ff4-4525-b6c3-1873320b7592.png" alt="" style="display:block;margin:0 auto" />

<h3>Final Takeaways</h3>
<p>Throughout this guide, you learned how to:</p>
<ul>
<li><p>Scan container images with Docker Scout.</p>
</li>
<li><p>Analyze and prioritize vulnerabilities.</p>
</li>
<li><p>Upgrade to recommended base images.</p>
</li>
<li><p>Generate an SBOM.</p>
</li>
<li><p>Reduce image size using Multi-Stage Builds.</p>
</li>
<li><p>Optimize the build context with <code>.dockerignore</code>.</p>
</li>
<li><p>Secure containers using Docker Hardened Images.</p>
</li>
<li><p>Troubleshoot containers with Docker Debug.</p>
</li>
<li><p>Run local AI models using Docker Model Runner.</p>
</li>
<li><p>Improve Docker projects with Ask Gordon AI.</p>
</li>
</ul>
<p>These practices help you build <strong>lighter, more secure, and production-ready Docker images</strong> while following modern DevSecOps workflows.</p>
<h3>Conclusion</h3>
<p>Building a Docker image is only the first step. A production-ready container should also be scanned, optimized, documented, and regularly maintained.</p>
<p>By combining Docker Scout, Multi-Stage Builds, Docker Hardened Images, SBOM generation, Docker Debug, Docker Model Runner, and Ask Gordon AI, you can create containers that are easier to maintain, more secure, and better prepared for real-world deployments.</p>
<p>Continue exploring new Docker features, keep your base images updated, and make security a regular part of your container development workflow.</p>
<h2><strong>👨‍💻 About the Author</strong></h2>
<p><strong>Hi, I'm Apurv Gujjar</strong>, a DevOps Engineer passionate about Cloud, AWS, Kubernetes, Docker, Terraform, GitLab, and Infrastructure Automation.</p>
<p>I share practical DevOps tutorials, real-world projects, certification guides, interview preparation, and cloud engineering best practices to help students and professionals build production-ready skills.</p>
<h2><strong>📬 Connect With Me</strong></h2>
<p>📧 <strong>Email:</strong> <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
<p>🌐 <strong>Portfolio:</strong> <a href="https://www.apurv-gujjar.co.in"><strong>https://www.apurv-gujjar.co.in</strong></a></p>
<p>🐙 <strong>GitHub:</strong> <a href="https://github.com/ApurvGujjar07"><strong>https://github.com/ApurvGujjar07</strong></a></p>
<p>💼 <strong>LinkedIn:</strong> <a href="https://www.linkedin.com/in/apurv-gujjar"><strong>https://www.linkedin.com/in/apurv-gujjar</strong></a></p>
<p>If you enjoy DevOps, Cloud, and GitLab content, feel free to connect with me. I'm always happy to share knowledge and discuss modern cloud technologies.</p>
]]></content:encoded></item><item><title><![CDATA[Day 3: Working with GitLab Repositories]]></title><description><![CDATA[Import Repositories, Mirroring & Repository Management Best Practices
📖 Introduction
In the previous articles, we learned the fundamentals of GitLab, created projects, and configured secure authentic]]></description><link>https://apurv-gujjar.me/day-3-working-with-gitlab-repositories</link><guid isPermaLink="true">https://apurv-gujjar.me/day-3-working-with-gitlab-repositories</guid><category><![CDATA[GitLab]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[repository]]></category><category><![CDATA[Linux]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 19 Jul 2026 08:18:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/cbb68e9c-021c-435b-9873-3c286d73c85d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Import Repositories, Mirroring &amp; Repository Management Best Practices</strong></p>
<h2>📖 Introduction</h2>
<p>In the previous articles, we learned the fundamentals of GitLab, created projects, and configured secure authentication using SSH Keys and Personal Access Tokens.</p>
<p>Now it's time to start working with <strong>GitLab repositories</strong>.</p>
<p>In this guide, you'll learn how to migrate existing repositories from GitHub, keep repositories synchronized using mirroring, understand the difference between <strong>Merge Requests</strong> and <strong>Pull Requests</strong>, and follow repository management best practices used by professional DevOps teams.</p>
<p>By the end of this article, you'll know how to manage GitLab repositories efficiently in both personal and enterprise environments.</p>
<h2>🎯 What You'll Learn</h2>
<p>After completing this article, you'll understand:</p>
<ul>
<li><p>✅ Import a GitHub repository into GitLab</p>
</li>
<li><p>✅ Repository Mirroring</p>
</li>
<li><p>✅ Push Mirroring vs Pull Mirroring</p>
</li>
<li><p>✅ Merge Request vs Pull Request</p>
</li>
<li><p>✅ Repository Management Best Practices</p>
</li>
</ul>
<h2>📚 Prerequisites</h2>
<p>Before continuing, make sure you have:</p>
<ul>
<li><p>A GitLab account</p>
</li>
<li><p>A GitHub account</p>
</li>
<li><p>Basic knowledge of Git</p>
</li>
<li><p>An existing Git repository (optional)</p>
</li>
</ul>
<h2><strong>📥 Importing a GitHub Repository into GitLab</strong></h2>
<p>Many developers and organizations already host their source code on <strong>GitHub</strong>. If you decide to use GitLab for its powerful CI/CD, security features, or DevOps platform, you don't need to recreate your repositories from scratch.</p>
<p>GitLab provides a built-in <strong>Import Project</strong> feature that allows you to migrate an existing GitHub repository—including its commit history—to GitLab in just a few steps.</p>
<p>This makes migration simple while preserving your existing development history.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0ba25cf1-758e-4034-b1c6-eaca1ce26446.png" alt="" style="display:block;margin:0 auto" />

<h2>🔍 Why Import a Repository?</h2>
<p>Importing a repository saves time and ensures that your existing project history remains intact.</p>
<p>Common reasons to import a repository include:</p>
<ul>
<li><p>Migrating from GitHub to GitLab</p>
</li>
<li><p>Using GitLab CI/CD with an existing project</p>
</li>
<li><p>Consolidating repositories into one platform</p>
</li>
<li><p>Moving company projects to GitLab</p>
</li>
</ul>
<h2>🚀 Steps to Import a GitHub Repository</h2>
<p>Follow these steps to import your repository into GitLab.</p>
<h3><strong>Step 1:</strong> Sign in to GitLab</h3>
<p>Log in to your GitLab account and click <strong>Project</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/728af883-16eb-48a2-8264-d4c7cb1458c6.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>Step 2:</strong> Choose <strong>Import Project</strong></h3>
<p>Select <strong>Import Project</strong>, then choose <strong>GitHub</strong> as the import source.</p>
<h3><strong>Step 3:</strong> Authorize GitHub</h3>
<p>GitLab will ask you to authorize access to your GitHub account.</p>
<p>Grant the required permissions so GitLab can read your repositories.</p>
<h3><strong>Step 4:</strong> Select the Repository</h3>
<p>Choose the repository you want to import and click <strong>Import</strong>.</p>
<p>GitLab will automatically copy the repository, including its commit history.</p>
<h3><strong>Step 5:</strong> Verify the Import</h3>
<p>Once the import is complete, open the repository in GitLab and verify that:</p>
<ul>
<li><p>Source code is available</p>
</li>
<li><p>Commit history is preserved</p>
</li>
<li><p>Branches are imported successfully</p>
</li>
</ul>
<p>Your project is now ready to use in GitLab.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/08649263-1130-4a71-9b59-d84fd3ac38ae.png" alt="" style="display:block;margin:0 auto" />

<h2>🔄 Repository Mirroring</h2>
<p>Repository Mirroring is a feature that automatically synchronizes repositories between GitLab and another Git hosting platform, such as GitHub, Bitbucket, or another GitLab instance.</p>
<p>Instead of manually pushing or pulling changes, GitLab keeps the repositories synchronized based on the configured mirroring direction.</p>
<p>Repository mirroring is especially useful for organizations managing projects across multiple Git platforms or maintaining backup repositories.</p>
<h2>🤔 Why Use Repository Mirroring?</h2>
<p>Repository mirroring helps keep code synchronized across different platforms without requiring manual intervention.</p>
<p>Common use cases include:</p>
<ul>
<li><p>Migrating from GitHub to GitLab gradually</p>
</li>
<li><p>Maintaining a backup repository</p>
</li>
<li><p>Synchronizing code across multiple Git platforms</p>
</li>
<li><p>Supporting teams working on different Git hosting services</p>
</li>
</ul>
<h2>🔀 Types of Repository Mirroring</h2>
<p>GitLab supports two types of repository mirroring:</p>
<ul>
<li><p><strong>Pull Mirroring</strong></p>
</li>
<li><p><strong>Push Mirroring</strong></p>
</li>
</ul>
<p>The difference lies in the direction in which changes are synchronized.</p>
<h2>⬇️ Pull Mirroring</h2>
<p>In Pull Mirroring, GitLab periodically <strong>pulls changes</strong> from another remote repository and updates the local GitLab repository automatically.</p>
<p>Whenever new commits are pushed to the source repository, GitLab fetches those changes during the next synchronization.</p>
<h3>Example</h3>
<pre><code class="language-plaintext">GitHub Repository
        │
        │ Pull Changes
        ▼
GitLab Repository
</code></pre>
<h3>Best Use Cases</h3>
<ul>
<li><p>Migrating repositories from GitHub</p>
</li>
<li><p>Keeping GitLab updated from another platform</p>
</li>
<li><p>Read-only synchronization</p>
</li>
</ul>
<h2>⬆️ Push Mirroring</h2>
<p>In Push Mirroring, GitLab automatically <strong>pushes changes</strong> from its repository to another remote repository whenever new commits are added.</p>
<p>This ensures that both repositories remain synchronized.</p>
<h3>Example</h3>
<pre><code class="language-plaintext">GitLab Repository
        │
        │ Push Changes
        ▼
GitHub Repository
</code></pre>
<h3>Best Use Cases</h3>
<ul>
<li><p>Maintaining backup repositories</p>
</li>
<li><p>Publishing code to multiple Git platforms</p>
</li>
<li><p>Disaster recovery strategies</p>
</li>
</ul>
<h2>⚖️ Pull Mirroring vs Push Mirroring</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Pull Mirroring</th>
<th>Push Mirroring</th>
</tr>
</thead>
<tbody><tr>
<td>Direction</td>
<td>External Repository → GitLab</td>
<td>GitLab → External Repository</td>
</tr>
<tr>
<td>Updates Triggered By</td>
<td>External repository changes</td>
<td>GitLab repository changes</td>
</tr>
<tr>
<td>Primary Purpose</td>
<td>Import and synchronize code</td>
<td>Backup and distribution</td>
</tr>
<tr>
<td>Common Use Case</td>
<td>GitHub to GitLab migration</td>
<td>GitLab to GitHub backup</td>
</tr>
</tbody></table>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d1d6b7d9-fb5f-4f2b-9e64-065cf06cac67.png" alt="" style="display:block;margin:0 auto" />

<h1>🔀 Merge Request vs Pull Request</h1>
<p>If you've worked with GitHub before, you've probably heard the term <strong>Pull Request (PR)</strong>. In GitLab, the same concept is called a <strong>Merge Request (MR)</strong>.</p>
<p>Both are used to propose code changes, review them, discuss improvements, and merge them into the main branch. The primary difference is the terminology used by each platform.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/31cd3ece-3f4e-4a93-9154-aefdca8307a2.png" alt="" style="display:block;margin:0 auto" />

<h2>🤔 What is a Merge Request?</h2>
<p>A <strong>Merge Request (MR)</strong> is a GitLab feature that allows developers to propose changes from one branch to another before merging.</p>
<p>Instead of directly pushing code to the main branch, developers create a Merge Request so teammates can review the changes, suggest improvements, run CI/CD pipelines, and approve the code.</p>
<p>This review process helps maintain code quality and reduces the chances of introducing bugs into production.</p>
<h2>🤔 What is a Pull Request?</h2>
<p>A <strong>Pull Request (PR)</strong> is GitHub's implementation of the same workflow.</p>
<p>After completing work on a feature branch, developers open a Pull Request to request that their changes be merged into another branch, usually the <strong>main</strong> or <strong>develop</strong> branch.</p>
<p>Like Merge Requests, Pull Requests support code reviews, comments, approvals, and automated CI/CD checks.</p>
<h2>💼 Real-World Example</h2>
<p>Imagine you're developing a new login feature.</p>
<p>Instead of committing your changes directly to the <strong>main</strong> branch, you create a separate feature branch.</p>
<p>After completing the feature, you open a <strong>Merge Request</strong> (or <strong>Pull Request</strong> in GitHub).</p>
<p>Your teammates review the code, provide feedback, and approve the changes. Once all checks pass, the feature is merged into the main branch.</p>
<h2>This workflow helps teams collaborate safely while maintaining high code quality.</h2>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0340ca19-926b-418e-a670-2e44be0c42b9.png" alt="" style="display:block;margin:0 auto" />

<h2>📂 Repository Management Best Practices</h2>
<p>A well-managed repository is easier to maintain, collaborate on, and scale as your project grows. Following repository management best practices helps improve code quality, reduces conflicts, and makes collaboration more efficient.</p>
<p>Whether you're working on a personal project or contributing to an enterprise application, adopting these practices from the beginning will save time and effort in the long run.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/22ae66bf-244e-4508-bb9a-6c3a61f45e12.png" alt="" style="display:block;margin:0 auto" />

<h2>✅ 1. Use a Clear Repository Structure</h2>
<p>Organize your project with a consistent folder structure so developers can easily navigate the codebase.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ac13950b-762d-40d0-9804-cdd5cb7955cc.png" alt="" style="display:block;margin:0 auto" />

<h2>✅ 2. Write a Good README</h2>
<p>A <a href="http://README.md"><strong>README.md</strong></a> file is often the first thing contributors see. It should explain:</p>
<ul>
<li><p>Project overview</p>
</li>
<li><p>Installation steps</p>
</li>
<li><p>Usage instructions</p>
</li>
<li><p>Prerequisites</p>
</li>
<li><p>Contribution guidelines</p>
</li>
</ul>
<p>A well-written README helps new developers get started quickly.</p>
<h2>✅ 3. Use Meaningful Branch Names</h2>
<p>Avoid generic branch names like:</p>
<pre><code class="language-plaintext">test
new
abc
</code></pre>
<p>Instead, use descriptive names such as:</p>
<pre><code class="language-plaintext">feature/user-authentication
bugfix/login-error
hotfix/payment-api
</code></pre>
<p>Meaningful branch names make collaboration easier and improve project organization.</p>
<h2>✅ 4. Protect Important Branches</h2>
<p>Protect critical branches like <strong>main</strong> and <strong>develop</strong> to prevent accidental changes.</p>
<p>Instead of pushing directly, require developers to submit <strong>Merge Requests</strong> for review and approval.</p>
<p>This helps maintain code quality and reduces the risk of introducing bugs.</p>
<h2>✅ 5. Keep Commit Messages Clear</h2>
<p>Write commit messages that describe what changed.</p>
<p>✅ Good Examples:</p>
<pre><code class="language-plaintext">Add user authentication API

Fix Docker build issue

Update Kubernetes deployment configuration
</code></pre>
<p>❌ Avoid:</p>
<pre><code class="language-plaintext">update

fix

changes
</code></pre>
<p>Clear commit messages make it easier to understand project history.</p>
<h2>✅ 6. Review Code Before Merging</h2>
<p>Always review code through a <strong>Merge Request</strong> before merging it into the main branch.</p>
<p>Code reviews help:</p>
<ul>
<li><p>Identify bugs early</p>
</li>
<li><p>Improve code quality</p>
</li>
<li><p>Share knowledge across the team</p>
</li>
<li><p>Maintain coding standards</p>
</li>
</ul>
<h2>✅ 7. Keep Documentation Updated</h2>
<p>As the project evolves, update your documentation regularly.</p>
<p>Important files include:</p>
<ul>
<li><p><a href="http://README.md">README.md</a></p>
</li>
<li><p><a href="http://CHANGELOG.md">CHANGELOG.md</a></p>
</li>
<li><p><a href="http://CONTRIBUTING.md">CONTRIBUTING.md</a></p>
</li>
<li><p>Project Wiki</p>
</li>
</ul>
<p>Up-to-date documentation makes onboarding and maintenance much easier.</p>
<h2>🎯 Summary</h2>
<p>Congratulations! 🎉 You have successfully completed <strong>Day 3</strong> of the GitLab learning series.</p>
<p>In this article, you learned how to import existing GitHub repositories into GitLab, synchronize repositories using <strong>Repository Mirroring</strong>, understand the difference between <strong>Merge Requests</strong> and <strong>Pull Requests</strong>, and follow repository management best practices used by professional development teams.</p>
<p>These concepts form the foundation of an efficient Git workflow and prepare you for collaborating on real-world software projects using GitLab.</p>
<h2><strong>👨‍💻 About the Author</strong></h2>
<p><strong>Hi, I'm Apurv Gujjar</strong>, a DevOps Engineer passionate about Cloud, AWS, Kubernetes, Docker, Terraform, GitLab, and Infrastructure Automation.</p>
<p>I share practical DevOps tutorials, real-world projects, certification guides, interview preparation, and cloud engineering best practices to help students and professionals build production-ready skills.</p>
<h2><strong>📬 Connect With Me</strong></h2>
<p>📧 <strong>Email:</strong> <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
<p>🌐 <strong>Portfolio:</strong> <a href="https://www.apurv-gujjar.co.in"><strong>https://www.apurv-gujjar.co.in</strong></a></p>
<p>🐙 <strong>GitHub:</strong> <a href="https://github.com/ApurvGujjar07"><strong>https://github.com/ApurvGujjar07</strong></a></p>
<p>💼 <strong>LinkedIn:</strong> <a href="https://www.linkedin.com/in/apurv-gujjar"><strong>https://www.linkedin.com/in/apurv-gujjar</strong></a></p>
<p>If you enjoy DevOps, Cloud, and GitLab content, feel free to connect with me. I'm always happy to share knowledge and discuss modern cloud technologies.</p>
]]></content:encoded></item><item><title><![CDATA[Day 2: GitLab Projects, Groups & Secure Authentication]]></title><description><![CDATA[Organizing Projects and Accessing GitLab Repositories Securely

Learn how GitLab organizes repositories using Groups and Projects, and understand how to securely authenticate using Personal Access Tok]]></description><link>https://apurv-gujjar.me/day-2-gitlab-projects-groups-secure-authentication</link><guid isPermaLink="true">https://apurv-gujjar.me/day-2-gitlab-projects-groups-secure-authentication</guid><category><![CDATA[GitLab]]></category><category><![CDATA[ec2]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Devops]]></category><category><![CDATA[automation]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[Jenkins]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 19 Jul 2026 06:54:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9014dca4-2790-450f-9899-77da385b8d37.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Organizing Projects and Accessing GitLab Repositories Securely</h3>
<blockquote>
<p>Learn how GitLab organizes repositories using Groups and Projects, and understand how to securely authenticate using Personal Access Tokens (PAT), SSH Keys, and Single Sign-On (SSO).</p>
</blockquote>
<h2>📖 Introduction</h2>
<p>In the previous article, we explored the fundamentals of GitLab, including its architecture, deployment models, and how it compares with GitHub and Bitbucket.</p>
<p>Now that we have a solid understanding of GitLab, it's time to learn how repositories are organized and how developers securely access them.</p>
<p>Whether you're working individually or as part of a large development team, understanding <strong>Groups</strong>, <strong>Projects</strong>, and <strong>authentication methods</strong> is essential. These concepts help organizations manage repositories efficiently while ensuring secure collaboration across teams.</p>
<p>In this article, we'll explore how GitLab organizes projects, how authentication works, and how to securely connect to GitLab repositories using <strong>Personal Access Tokens (PAT)</strong> and <strong>SSH Keys</strong>. We'll also learn how to configure an AWS EC2 instance to communicate with GitLab using SSH authentication.</p>
<p>By the end of this guide, you'll be able to organize projects like a professional DevOps engineer and securely interact with GitLab repositories.</p>
<h2>🎯 What You'll Learn</h2>
<p>After completing this article, you'll understand:</p>
<ul>
<li><p>✅ What are GitLab Groups?</p>
</li>
<li><p>✅ What are GitLab Projects?</p>
</li>
<li><p>✅ Difference between Groups and Projects</p>
</li>
<li><p>✅ GitLab Project Structure</p>
</li>
<li><p>✅ Git Authentication</p>
</li>
<li><p>✅ Personal Access Tokens (PAT)</p>
</li>
<li><p>✅ SSH Keys</p>
</li>
<li><p>✅ Single Sign-On (SSO)</p>
</li>
<li><p>✅ SSH Authentication Setup</p>
</li>
<li><p>✅ Cloning a Repository using SSH</p>
</li>
</ul>
<h2>📚 Prerequisites</h2>
<p>Before continuing, make sure you have:</p>
<ul>
<li><p>A GitLab Account</p>
</li>
<li><p>Git Installed on your system</p>
</li>
<li><p>Basic knowledge of Git commands</p>
</li>
<li><p>A Linux machine or AWS EC2 instance (optional for practice)</p>
</li>
</ul>
<h2>👥 What are GitLab Groups?</h2>
<p>As organizations grow, managing hundreds of repositories individually becomes difficult. To solve this problem, GitLab provides <strong>Groups</strong>.</p>
<p>A <strong>Group</strong> is a container that helps organize multiple related projects under a single team or organization. Instead of managing users and permissions separately for each repository, administrators can manage everything at the group level.</p>
<p>For example, if a company has separate repositories for a frontend application, backend API, Kubernetes manifests, and Terraform configurations, all of them can be placed inside a single group.</p>
<p>This approach makes collaboration easier, simplifies permission management, and keeps projects well organized.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/68a09e3f-8cd2-46e0-bf88-193c053cb03a.png" alt="" style="display:block;margin:0 auto" />

<h2>Example</h2>
<p>Imagine your company is called <strong>ABC Technologies</strong>.</p>
<p>Inside the company, there's a <strong>DevOps Team</strong> responsible for managing cloud infrastructure and application deployments.</p>
<p>The DevOps team may create a single GitLab Group called <strong>DevOps-Team</strong>, which contains multiple projects.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/bf487fda-c84a-4c31-ab5e-71d4c0f287eb.png" alt="" style="display:block;margin:0 auto" />

<h2>Why Use Groups?</h2>
<p>Using Groups provides several advantages:</p>
<ul>
<li><p>Better project organization</p>
</li>
<li><p>Easier permission management</p>
</li>
<li><p>Improved collaboration</p>
</li>
<li><p>Simplified administration</p>
</li>
<li><p>Centralized access control</p>
</li>
</ul>
<p>Groups are especially useful for organizations managing multiple teams and repositories.</p>
<h2>📁 What are GitLab Projects?</h2>
<p>A <strong>Project</strong> is the place where your actual application or source code is stored in GitLab. Every project contains everything related to a specific application, service, or repository, including its source code, branches, commits, Merge Requests, issues, and CI/CD pipelines.</p>
<p>In simple terms, if a <strong>Group</strong> represents a team or organization, then a <strong>Project</strong> represents the actual application or repository that the team is working on.</p>
<p>For example, a company may have different applications such as a frontend website, backend API, Kubernetes manifests, and Terraform code. Each of these would typically be created as a separate project within the same GitLab Group.</p>
<h2>Example</h2>
<p>Let's continue with the previous example.</p>
<p>Suppose your organization has a Group named <strong>DevOps-Team</strong>.</p>
<p>Inside this Group, you can create multiple projects, each serving a different purpose.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f5cf6059-7695-4520-a1d2-de435117a6b9.png" alt="" style="display:block;margin:0 auto" />

<h2>Why Use Projects?</h2>
<p>Projects help organize your work efficiently by keeping each application or service in its own dedicated repository.</p>
<p>Some benefits of using Projects include:</p>
<ul>
<li><p>Store source code securely</p>
</li>
<li><p>Manage Git branches and commits</p>
</li>
<li><p>Collaborate using Merge Requests</p>
</li>
<li><p>Automate CI/CD pipelines</p>
</li>
<li><p>Track issues and bugs</p>
</li>
<li><p>Maintain project documentation</p>
</li>
</ul>
<p>Whether you're developing a simple application or managing enterprise infrastructure, every repository in GitLab is created as a <strong>Project</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/491d9d70-d477-4758-a084-fc59cc4de792.png" alt="" style="display:block;margin:0 auto" />

<h2>🔄 Groups vs Projects</h2>
<p>One of the most common questions beginners ask is:</p>
<blockquote>
<p><strong>"What is the difference between a Group and a Project?"</strong></p>
</blockquote>
<p>The answer is simple.</p>
<p>A <strong>Group</strong> is used to organize and manage multiple related projects, whereas a <strong>Project</strong> is where the actual application or source code resides.</p>
<p>Think of a Group as a company department and a Project as the individual applications that department is responsible for.</p>
<p>For example, a DevOps team may manage several applications, infrastructure code, and automation scripts. Instead of creating everything separately, they organize all related repositories under a single Group.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b854750f-22a6-4125-b13c-56d5ec946588.png" alt="" style="display:block;margin:0 auto" />

<h2>🎯 When Should You Use a Group?</h2>
<p>Create a <strong>Group</strong> when:</p>
<ul>
<li><p>You have multiple related repositories.</p>
</li>
<li><p>Multiple developers work on different projects.</p>
</li>
<li><p>You want centralized permission management.</p>
</li>
<li><p>You're managing projects for a team or organization.</p>
</li>
</ul>
<h2>🎯 When Should You Use a Project?</h2>
<p>Create a <strong>Project</strong> when:</p>
<ul>
<li><p>You're starting a new application.</p>
</li>
<li><p>You need a separate Git repository.</p>
</li>
<li><p>You want an independent CI/CD pipeline.</p>
</li>
<li><p>You need to track issues and manage code for a specific application.</p>
</li>
</ul>
<h2>🔐 Git Authentication in GitLab</h2>
<p>Before you can clone, push, or pull code from a GitLab repository, GitLab must verify your identity. This process is known as <strong>Git Authentication</strong>.</p>
<p>In the past, many Git hosting platforms allowed users to authenticate using their account password. However, this approach was not secure because passwords could be exposed or misused.</p>
<p>To improve security, GitLab no longer supports using your account password for Git operations over HTTPS. Instead, it uses more secure authentication methods such as <strong>Personal Access Tokens (PAT)</strong>, <strong>SSH Keys</strong>, and <strong>Single Sign-On (SSO)</strong>.</p>
<p>These authentication methods help protect repositories while ensuring that only authorized users can access and modify the source code.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/2721b37a-fdc9-4e5c-9300-8f58ad04227e.png" alt="" style="display:block;margin:0 auto" />

<h2>🔑 Authentication Methods in GitLab</h2>
<p>GitLab provides three primary authentication methods:</p>
<h3>1️⃣ SSH Keys</h3>
<p>SSH authentication uses a public-private key pair to securely connect your system with GitLab. Once configured, you can clone, pull, and push repositories without entering your credentials every time.</p>
<p><strong>Best for:</strong> Developers and DevOps Engineers who work with Git repositories regularly.</p>
<h3>2️⃣ Personal Access Token (PAT)</h3>
<p>A Personal Access Token acts as a secure replacement for your account password when performing Git operations over HTTPS.</p>
<p>Instead of entering your GitLab password, you use the generated token.</p>
<p><strong>Best for:</strong> HTTPS-based Git operations and API integrations.</p>
<h3>3️⃣ Single Sign-On (SSO)</h3>
<p>Large organizations often use Single Sign-On (SSO) to allow employees to log in using their company identity providers, such as <strong>Microsoft Entra ID (Azure AD)</strong>, <strong>Okta</strong>, or <strong>Google Workspace</strong>.</p>
<p>This simplifies user management while improving security and enforcing organizational policies.</p>
<p><strong>Best for:</strong> Enterprise environments.v</p>
<h2>🎫 Personal Access Token (PAT)</h2>
<p>A <strong>Personal Access Token (PAT)</strong> is a secure authentication credential used instead of your GitLab account password for Git operations over HTTPS.</p>
<p>Earlier, users could clone, push, and pull repositories using their GitLab username and password. However, this method was less secure and increased the risk of credential exposure.</p>
<p>To improve security, GitLab now recommends using a <strong>Personal Access Token (PAT)</strong> for HTTPS authentication instead of your account password.</p>
<p>Think of a PAT as a temporary password that is generated specifically for Git operations. Unlike your account password, a PAT can be limited to specific permissions and revoked at any time without affecting your account login.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a3065e95-6d6d-4b6b-b60f-3762f15c25d5.png" alt="" style="display:block;margin:0 auto" />

<h2>📌 Why Use a Personal Access Token?</h2>
<p>Using a PAT provides several security benefits:</p>
<ul>
<li><p>Secure alternative to account passwords.</p>
</li>
<li><p>Can be revoked anytime without changing your account password.</p>
</li>
<li><p>Permissions can be restricted using scopes.</p>
</li>
<li><p>Commonly used for Git over HTTPS and API access.</p>
</li>
<li><p>Reduces the risk of exposing your actual login credentials.</p>
</li>
</ul>
<h2>📍 Where Can You Create a PAT?</h2>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/5edb7a50-44c9-40c5-9a6d-f980e9b53113.png" alt="" style="display:block;margin:0 auto" />

<h2>🔧 Common Use Cases</h2>
<p>A Personal Access Token is commonly used when:</p>
<ul>
<li><p>Cloning a repository over HTTPS.</p>
</li>
<li><p>Pushing code to GitLab.</p>
</li>
<li><p>Pulling the latest changes.</p>
</li>
<li><p>Accessing the GitLab REST API.</p>
</li>
<li><p>Integrating GitLab with third-party tools.</p>
</li>
</ul>
<h2>🔑 SSH Keys</h2>
<p>An <strong>SSH Key</strong> is one of the most secure and recommended ways to authenticate with GitLab. Instead of entering your username and password every time you interact with a repository, SSH uses a <strong>public-private key pair</strong> to verify your identity.</p>
<p>Once your SSH key is configured, you can clone, pull, and push code securely without repeatedly entering your credentials.</p>
<p>This is why most DevOps Engineers and software developers prefer SSH authentication for their daily workflow.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/408153ee-955f-44fd-bfe5-57b5372d8029.png" alt="" style="display:block;margin:0 auto" />

<h2>🔍 How SSH Authentication Works</h2>
<p>SSH authentication works using two keys:</p>
<ul>
<li><p><strong>Private Key</strong> – Stored securely on your local machine. Never share this key with anyone.</p>
</li>
<li><p><strong>Public Key</strong> – Uploaded to your GitLab account so GitLab can verify your identity.</p>
</li>
</ul>
<p>When you connect to GitLab, it verifies your private key against the stored public key. If they match, access is granted without asking for your password.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/438a375a-2560-4647-9595-aaa5ce87d9c6.png" alt="" style="display:block;margin:0 auto" />

<h2>🚀 Why Use SSH Keys?</h2>
<p>SSH authentication offers several advantages over password-based authentication:</p>
<ul>
<li><p>More secure than passwords</p>
</li>
<li><p>No need to enter credentials repeatedly</p>
</li>
<li><p>Faster Git operations</p>
</li>
<li><p>Ideal for developers and DevOps engineers</p>
</li>
<li><p>Widely used in production environments</p>
</li>
</ul>
<h2>🛠️ Basic SSH Setup</h2>
<p>Setting up SSH authentication involves four simple steps:</p>
<h3>Step 1: Generate an SSH Key Pair</h3>
<p>Run the following command on your local machine or server.</p>
<pre><code class="language-shell">ssh-keygen
</code></pre>
<p>This command generates both the <strong>private key</strong> and the <strong>public key</strong>.</p>
<h3>Step 2: View the Public Key</h3>
<p>Display the public key using:</p>
<pre><code class="language-shell">cat ~/.ssh/id_rsa.pub
</code></pre>
<p>Copy the entire output.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1b462509-da58-4152-8612-e0d1d342fa4b.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f7ad2414-d767-4f29-8232-106bad47816e.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 4: Clone the Repository Using SSH</h3>
<p>After adding your SSH key, copy the repository's <strong>SSH URL</strong>.</p>
<p>Example:</p>
<pre><code class="language-shell">git@gitlab.com:group-name/project-name.git
</code></pre>
<p>Now clone the repository:</p>
<pre><code class="language-shell">git clone git@gitlab.com:group-name/project-name.git
</code></pre>
<p>Once configured, Git will authenticate automatically using your SSH key.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/bc2ef218-3bf4-4a27-b40f-23859ea53c39.png" alt="" style="display:block;margin:0 auto" />

<h2>🏢 Single Sign-On (SSO)</h2>
<p><strong>Single Sign-On (SSO)</strong> is an authentication method that allows users to access GitLab using their organization's existing identity provider instead of creating and managing a separate GitLab password.</p>
<p>In most enterprise environments, employees already have company accounts managed by services such as <strong>Microsoft Entra ID (Azure AD)</strong>, <strong>Okta</strong>, <strong>Google Workspace</strong>, or other identity providers. With SSO, users can sign in to GitLab using these existing accounts, making authentication both secure and convenient.</p>
<p>Instead of remembering multiple usernames and passwords for different applications, users authenticate once through their organization's identity provider and gain access to GitLab based on the permissions assigned by the organization.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f5fc1c81-c8e9-4d89-a074-7727a46cf686.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>🔍 How SSO Works</strong></h2>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ef7bc45f-9750-4b74-b70d-542d64c73749.png" alt="" style="display:block;margin:0 auto" />

<p>When a user attempts to log in to GitLab, they are redirected to the organization's identity provider. After successful authentication, the identity provider securely verifies the user's identity and grants access to GitLab.</p>
<h2>🚀 Benefits of Using SSO</h2>
<p>Organizations prefer SSO because it improves both security and user management.</p>
<p>Some key benefits include:</p>
<ul>
<li><p>Users log in with their company credentials.</p>
</li>
<li><p>No need to remember multiple passwords.</p>
</li>
<li><p>Centralized user and permission management.</p>
</li>
<li><p>Improved security through Multi-Factor Authentication (MFA).</p>
</li>
<li><p>Faster onboarding and offboarding of employees.</p>
</li>
<li><p>Reduced risk of unauthorized access.</p>
</li>
</ul>
<h2>🏢 Where is SSO Commonly Used?</h2>
<p>SSO is primarily used in large organizations and enterprises where hundreds or even thousands of employees need secure access to GitLab.</p>
<p>Some common use cases include:</p>
<ul>
<li><p>Large software companies</p>
</li>
<li><p>Banking and financial institutions</p>
</li>
<li><p>Government organizations</p>
</li>
<li><p>Healthcare companies</p>
</li>
<li><p>Enterprises with centralized identity management</p>
</li>
</ul>
<h2>🎯 Summary</h2>
<p>Congratulations! 🎉 You have successfully completed <strong>Day 2</strong> of the GitLab learning series.</p>
<p>In this chapter, you learned how GitLab organizes repositories using <strong>Groups</strong> and <strong>Projects</strong>, explored different authentication methods, and configured secure access from an AWS EC2 instance.</p>
<h2><strong>👨‍💻 About the Author</strong></h2>
<p><strong>Hi, I'm Apurv Gujjar</strong>, a DevOps Engineer passionate about Cloud, AWS, Kubernetes, Docker, Terraform, GitLab, and Infrastructure Automation.</p>
<p>I share practical DevOps tutorials, real-world projects, certification guides, interview preparation, and cloud engineering best practices to help students and professionals build production-ready skills.</p>
<h2><strong>📬 Connect With Me</strong></h2>
<p>📧 <strong>Email:</strong> <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
<p>🌐 <strong>Portfolio:</strong> <a href="https://www.apurv-gujjar.co.in"><strong>https://www.apurv-gujjar.co.in</strong></a></p>
<p>🐙 <strong>GitHub:</strong> <a href="https://github.com/ApurvGujjar07"><strong>https://github.com/ApurvGujjar07</strong></a></p>
<p>💼 <strong>LinkedIn:</strong> <a href="https://www.linkedin.com/in/apurv-gujjar"><strong>https://www.linkedin.com/in/apurv-gujjar</strong></a></p>
<p>If you enjoy DevOps, Cloud, and GitLab content, feel free to connect with me. I'm always happy to share knowledge and discuss modern cloud technologies.</p>
]]></content:encoded></item><item><title><![CDATA[Day 1: What is GitLab? The Complete Beginner's Guide for DevOps Engineers]]></title><description><![CDATA[Welcome to the GitLab Mastery Series

🚀 In this first lesson of the GitLab Mastery Series, you'll learn what GitLab is, why modern DevOps teams rely on it, and how it simplifies the complete Software]]></description><link>https://apurv-gujjar.me/day-1-what-is-gitlab-the-complete-beginner-s-guide-for-devops-engineers</link><guid isPermaLink="true">https://apurv-gujjar.me/day-1-what-is-gitlab-the-complete-beginner-s-guide-for-devops-engineers</guid><category><![CDATA[GitLab]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Git]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[Linux]]></category><category><![CDATA[version control]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 12 Jul 2026 05:38:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/142b295c-61b3-4b15-8798-0b4c4b40238c.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Welcome to the GitLab Mastery Series</h3>
<blockquote>
<p>🚀 In this first lesson of the GitLab Mastery Series, you'll learn what GitLab is, why modern DevOps teams rely on it, and how it simplifies the complete Software Development Life Cycle (SDLC).</p>
</blockquote>
<h2>📖 Introduction</h2>
<p>Welcome to the <strong>GitLab Mastery Series</strong>—your step-by-step guide to mastering GitLab from the basics to advanced DevOps workflows.</p>
<p>Whether you're aspiring to become a <strong>DevOps Engineer, Cloud Engineer, Platform Engineer, or Site Reliability Engineer (SRE)</strong>, GitLab is one of the most valuable tools you can learn. It's widely adopted by startups and enterprises to streamline software development, automate deployments, and improve team collaboration.</p>
<p>Modern software development is no longer just about writing code. Teams need to collaborate efficiently, automate software delivery, maintain security, and deploy applications faster with confidence. Managing these responsibilities using multiple disconnected tools can quickly become complex, time-consuming, and difficult to maintain.</p>
<p>This is where <strong>GitLab</strong> makes a difference.</p>
<p>More than just a Git repository hosting platform, GitLab is a complete <strong>end-to-end DevOps platform</strong> that helps teams manage the entire <strong>Software Development Life Cycle (SDLC)</strong> from a single application. It combines source code management, collaboration, built-in CI/CD, security scanning, package management, and deployment into one unified platform.</p>
<p>In this first article of the <strong>GitLab Mastery Series</strong>, you'll build a strong foundation by learning what GitLab is, why it was created, why organizations choose it over other platforms, how it compares with GitHub and Bitbucket, and how it supports modern DevOps workflows.</p>
<p>By the end of this guide, you'll have a clear understanding of GitLab fundamentals and be ready to dive into hands-on GitLab workflows in the upcoming lessons.</p>
<h2>🎯 What You'll Learn</h2>
<p>After completing this article, you'll understand:</p>
<ul>
<li><p>✅ What is GitLab?</p>
</li>
<li><p>✅ Why was GitLab created?</p>
</li>
<li><p>✅ GitLab Architecture</p>
</li>
<li><p>✅ GitHub vs GitLab</p>
</li>
<li><p>✅ GitHub vs Bitbucket</p>
</li>
<li><p>✅ Why enterprises choose GitLab</p>
</li>
<li><p>✅ GitLab Community Edition</p>
</li>
<li><p>✅ GitLab SaaS vs Self-Managed</p>
</li>
<li><p>✅ Creating a GitLab account</p>
</li>
<li><p>✅ GitLab account verification process</p>
</li>
</ul>
<h2>📚 Prerequisites</h2>
<p>Before getting started, you should have a basic understanding of:</p>
<ul>
<li><p>Basic Git concepts</p>
</li>
<li><p>Version Control System (VCS)</p>
</li>
<li><p>Basic Linux commands (Optional)</p>
</li>
</ul>
<blockquote>
<p><strong>Don't worry if you're completely new to GitLab. This series starts from absolute basics and gradually moves toward real-world DevOps implementations.</strong></p>
</blockquote>
<h2>📖 What is GitLab?</h2>
<p>GitLab is one of the most popular <strong>DevOps platforms</strong> that enables teams to manage the entire Software Development Life Cycle (SDLC) from a single application.</p>
<p>Unlike traditional Git repository hosting platforms, GitLab provides everything required to develop, test, secure, and deploy applications without relying on multiple third-party tools.</p>
<p><strong>GitLab is an all-in-one DevOps platform that combines Git repository hosting, source code management, collaboration, built-in CI/CD, testing, security, and deployment tools into a single platform.</strong></p>
<p>In simple terms, GitLab is much more than a place to store your source code. It allows development and operations teams to collaborate efficiently, automate software delivery, and continuously deploy applications using a unified platform.</p>
<p>Instead of using separate tools for version control, CI/CD, security scanning, and deployment, GitLab brings all these capabilities together, making software development faster, more secure, and easier to manage.</p>
<h2>🚀 Why is GitLab So Popular?</h2>
<p>Modern software development requires multiple teams to work together.</p>
<p>Developers write code, testers validate features, DevOps engineers automate deployments, and security teams ensure applications remain secure. Managing these workflows using different tools often leads to complex integrations, higher maintenance, and increased operational costs.</p>
<p>GitLab solves this challenge by providing a <strong>single platform</strong> where every stage of the DevOps lifecycle can be managed efficiently.</p>
<p>With GitLab, organizations can:</p>
<ul>
<li><p>Store and manage source code repositories.</p>
</li>
<li><p>Collaborate using Merge Requests and Code Reviews.</p>
</li>
<li><p>Automate Build, Test, and Deployment through CI/CD pipelines.</p>
</li>
<li><p>Perform security and compliance scans.</p>
</li>
<li><p>Deploy applications to cloud, virtual machines, or Kubernetes clusters.</p>
</li>
<li><p>Monitor the complete software delivery process from one interface.</p>
</li>
</ul>
<p>This unified approach is one of the biggest reasons why GitLab has become a preferred choice for startups, enterprises, and DevOps teams worldwide.</p>
<h2>🔑 Key Features of GitLab</h2>
<p>GitLab offers a wide range of built-in features that simplify the software development process.</p>
<p>Some of its most important capabilities include:</p>
<ul>
<li><p>Git Repository Hosting</p>
</li>
<li><p>Source Code Management (SCM)</p>
</li>
<li><p>Team Collaboration</p>
</li>
<li><p>Merge Requests (MR)</p>
</li>
<li><p>Built-in CI/CD Pipelines</p>
</li>
<li><p>DevSecOps Integration</p>
</li>
<li><p>Security Scanning</p>
</li>
<li><p>Container Registry</p>
</li>
<li><p>Package Registry</p>
</li>
<li><p>Issue Tracking</p>
</li>
<li><p>Project Management</p>
</li>
<li><p>Deployment Automation</p>
</li>
<li><p>Monitoring &amp; Observability</p>
</li>
</ul>
<p>Because all these capabilities are available within a single application, GitLab is often referred to as an <strong>All-in-One DevOps Platform</strong>.</p>
<h3>🔄 How GitLab Fits into the DevOps Lifecycle</h3>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/48b47d46-dc8f-44f1-a053-378dbfc46835.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/579b163a-f57f-4e26-87c3-0a1cfa0c931a.png" alt="" style="display:block;margin:0 auto" />

<p>As shown above, GitLab acts as the central platform that connects developers, testing, security, CI/CD, and deployment into a single automated workflow.</p>
<p>Instead of manually managing different tools for each phase, GitLab streamlines the complete software delivery process from code commit to production deployment.</p>
<h2>💡 Real-World Example</h2>
<p>Imagine a company developing an e-commerce application.</p>
<p>Every day:</p>
<ul>
<li><p>Developers write new features.</p>
</li>
<li><p>Testers verify application quality.</p>
</li>
<li><p>DevOps engineers automate deployments.</p>
</li>
<li><p>Security teams scan the application for vulnerabilities.</p>
</li>
</ul>
<p>Without GitLab, the company might need different tools such as GitHub, Jenkins, SonarQube, Docker Registry, and several deployment utilities.</p>
<p>With GitLab, all these activities can be managed from a single platform, reducing operational complexity while improving collaboration, automation, and software delivery speed.</p>
<h2>❓ Why Was GitLab Created?</h2>
<p>Before GitLab became popular, software development teams relied on multiple tools to manage different stages of the Software Development Life Cycle (SDLC).</p>
<p>For example, developers used one platform to host their source code, another tool to automate builds and deployments, a separate application for security scanning, and yet another tool for project management. While these tools worked individually, integrating and maintaining them required significant effort, increased operational costs, and often led to workflow inefficiencies.</p>
<p>As software projects grew in complexity, organizations realized the need for a unified platform that could streamline the entire development process.</p>
<p>This is where <strong>GitLab</strong> changed the game.</p>
<p>GitLab was created with a simple yet powerful vision:</p>
<blockquote>
<p><strong>Provide a single application for the complete DevOps lifecycle.</strong></p>
</blockquote>
<p>Instead of switching between multiple tools, development, operations, QA, and security teams could collaborate on one platform—from writing code to deploying applications into production.</p>
<p>Today, GitLab enables organizations to manage their complete software delivery pipeline within a single interface, helping teams deliver software faster, improve collaboration, and maintain higher security standards.</p>
<h2>🚧 Challenges Before GitLab</h2>
<p>Before platforms like GitLab existed, a typical DevOps workflow looked something like this:-</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/7a8eb4c5-0c70-4628-a03b-97193daa4159.png" alt="" style="display:block;margin:0 auto" />

<p>Although each tool performed its job well, teams had to spend considerable time integrating, configuring, and maintaining these separate systems.</p>
<p>Some common challenges included:</p>
<ul>
<li><p>Managing multiple tools with different interfaces.</p>
</li>
<li><p>Complex integrations between tools.</p>
</li>
<li><p>Higher infrastructure and maintenance costs.</p>
</li>
<li><p>Difficult user and permission management.</p>
</li>
<li><p>Slower software delivery.</p>
</li>
<li><p>Increased operational overhead.</p>
</li>
</ul>
<p>As organizations scaled, these challenges became even more significant.</p>
<h2>💡 How GitLab Solved These Problems</h2>
<p>GitLab introduced an <strong>all-in-one DevOps platform</strong> that combines multiple capabilities into a single application.</p>
<p>Instead of using separate tools, teams can perform almost every DevOps activity directly within GitLab.</p>
<p>With GitLab, you can:</p>
<ul>
<li><p>Host and manage Git repositories.</p>
</li>
<li><p>Collaborate using Merge Requests and Code Reviews.</p>
</li>
<li><p>Automate Build, Test, and Deployment using built-in CI/CD.</p>
</li>
<li><p>Store packages and container images.</p>
</li>
<li><p>Perform security and vulnerability scanning.</p>
</li>
<li><p>Manage projects, issues, milestones, and documentation.</p>
</li>
<li><p>Deploy applications to cloud platforms, virtual machines, or Kubernetes clusters.</p>
</li>
</ul>
<p>This unified approach simplifies software development while reducing operational complexity.</p>
<h2>🌍 Real-World Example</h2>
<p>Imagine a startup with a team of 20 developers building an e-commerce application.</p>
<p>Without GitLab, the team might use:</p>
<ul>
<li><p>GitHub for source code management.</p>
</li>
<li><p>Jenkins for CI/CD pipelines.</p>
</li>
<li><p>SonarQube for code quality analysis.</p>
</li>
<li><p>Docker Hub for container images.</p>
</li>
<li><p>Jira for project management.</p>
</li>
<li><p>Confluence for documentation.</p>
</li>
</ul>
<p>Managing permissions, integrations, updates, and authentication across all these platforms can quickly become difficult.</p>
<p>With GitLab, the same team can manage almost all these activities from a single platform.</p>
<p>This not only reduces maintenance effort but also improves collaboration, security, and deployment speed.</p>
<h2>🎯 Key Takeaway</h2>
<p>GitLab was created to eliminate the complexity of using multiple DevOps tools by providing a <strong>single, integrated platform</strong> for the entire Software Development Life Cycle.</p>
<p>Instead of managing separate tools for source code, CI/CD, security, and deployment, GitLab brings everything together—allowing teams to collaborate more efficiently, automate workflows, and deliver software faster with greater confidence.</p>
<h2>🏗️ GitLab Architecture</h2>
<p>To use GitLab effectively, it's important to understand how its core components work together. GitLab is designed around a simple yet powerful architecture that automates the entire software delivery process—from writing code to deploying applications into production.</p>
<p>Whenever a developer pushes code to a GitLab repository, GitLab can automatically trigger a CI/CD pipeline. The pipeline is then executed by a <strong>GitLab Runner</strong>, which performs tasks such as building the application, running tests, scanning for vulnerabilities, and deploying the application to the target environment.</p>
<p>This seamless workflow allows development teams to deliver software faster, reduce manual effort, and maintain consistent deployment processes.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9d1e02fc-c95e-4cd9-8816-a3aa159f5f18.png" alt="" style="display:block;margin:0 auto" />

<h2>⚔️ GitHub vs GitLab</h2>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/07d503ef-625b-4111-8b11-a752712deb7a.png" alt="" style="display:block;margin:0 auto" />

<p>If you've worked with Git before, you've probably heard about <strong>GitHub</strong> and <strong>GitLab</strong>. At first glance, both platforms may seem similar because they allow developers to host Git repositories and collaborate on code. However, they differ significantly in terms of features, DevOps capabilities, and overall workflow.</p>
<p>GitHub primarily focuses on <strong>Git repository hosting and collaboration</strong>, whereas GitLab is designed as a <strong>complete DevOps platform</strong> that supports the entire Software Development Life Cycle (SDLC) from development to deployment.</p>
<h2>💡 Which One Should You Choose?</h2>
<p>Choose <strong>GitHub</strong> if:</p>
<ul>
<li><p>You mainly host code repositories.</p>
</li>
<li><p>You contribute to open-source projects.</p>
</li>
<li><p>Your workflow already relies on GitHub Actions.</p>
</li>
<li><p>You prefer a large developer community.</p>
</li>
</ul>
<p>Choose <strong>GitLab</strong> if:</p>
<ul>
<li><p>You want an all-in-one DevOps platform.</p>
</li>
<li><p>You need built-in CI/CD without additional setup.</p>
</li>
<li><p>Your organization requires self-hosted deployments.</p>
</li>
<li><p>You want integrated security, automation, and deployment features.</p>
</li>
</ul>
<h2>⚖️ GitHub vs Bitbucket</h2>
<p>Along with GitHub and GitLab, <strong>Bitbucket</strong> is another popular Git repository hosting platform. While all three platforms use <strong>Git</strong> for version control, they are designed for different use cases.</p>
<p>GitHub is widely known for open-source collaboration, GitLab focuses on the complete DevOps lifecycle, whereas Bitbucket is primarily designed for teams already using <strong>Atlassian products</strong> such as Jira and Confluence.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/aae744ae-cb24-4bac-b35f-9336d4440109.png" alt="" style="display:block;margin:0 auto" />

<h2>🎯 Which Platform Should You Choose?</h2>
<p>Choose <strong>GitHub</strong> if you work on open-source projects or need a large developer community.</p>
<p>Choose <strong>Bitbucket</strong> if your organization already uses <strong>Jira</strong>, <strong>Confluence</strong>, and other Atlassian products, as it integrates seamlessly with them.</p>
<h2>🏢 Why Do Enterprises Choose GitLab?</h2>
<p>Modern enterprises don't just need a platform to store source code—they need a solution that can manage the entire software delivery lifecycle.</p>
<p>GitLab provides a single platform for <strong>source code management, CI/CD, security, project planning, and deployment</strong>, reducing the need to maintain multiple tools. This integrated approach simplifies DevOps workflows, improves collaboration, and lowers operational overhead.</p>
<p>One of the biggest reasons enterprises choose GitLab is its <strong>Community Edition</strong>, which allows organizations to self-host GitLab on their own infrastructure without licensing costs. This gives companies greater control over their data, security, and compliance requirements.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/96f66e5f-f69e-420e-845a-770a5f26d026.png" alt="" style="display:block;margin:0 auto" />

<h2>🌐 GitLab SaaS vs Self-Managed</h2>
<p>GitLab offers two deployment options: <strong>GitLab SaaS</strong> and <strong>GitLab Self-Managed</strong>. The right choice depends on your organization's infrastructure, security requirements, and operational needs.</p>
<p>If you simply want to start using GitLab without managing any servers, GitLab SaaS is the easiest option. On the other hand, organizations that require complete control over their infrastructure often choose the Self-Managed edition.</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/685ac8d8-c69c-4ce0-8a04-c5cb880cad01.png" alt="" style="display:block;margin:0 auto" />

<h1>👤 Creating a GitLab Account</h1>
<p>Before you can create repositories, collaborate with teams, or build CI/CD pipelines, you first need a GitLab account.</p>
<p>Creating an account is quick and completely free for learning and personal projects.</p>
<h2>📝 Steps to Create a GitLab Account</h2>
<ol>
<li><p>Visit the <strong>GitLab</strong> website.</p>
</li>
<li><p>Click <strong>Register</strong> or <strong>Sign Up</strong>.</p>
</li>
<li><p>Enter your:</p>
<ul>
<li><p>Name</p>
</li>
<li><p>Username</p>
</li>
<li><p>Email Address</p>
</li>
<li><p>Password</p>
</li>
</ul>
</li>
<li><p>Accept the Terms and Conditions.</p>
</li>
<li><p>Click <strong>Continue</strong> to create your account.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/672cc5e4-e718-4fff-befa-c2d0112c5eb1.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0b416f4e-0dab-4151-9fd5-ef2a4a32b7d5.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a5076fae-b14e-4e63-a095-0189cce7ff74.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1471472b-2871-421b-8fe9-f647cb3661d7.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/fcd16ff6-469d-4144-b3d9-47e558c3c0cd.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9ac20987-96b5-47d7-9880-7d71b14b9931.png" alt="" style="display:block;margin:0 auto" />

<h2>📝 Summary</h2>
<p>Congratulations! 🎉 You have successfully completed <strong>Day 1</strong> of the GitLab series.</p>
<p>In this article, you learned:</p>
<ul>
<li><p>✅ What GitLab is</p>
</li>
<li><p>✅ Why GitLab was created</p>
</li>
<li><p>✅ GitLab Architecture</p>
</li>
<li><p>✅ GitHub vs GitLab</p>
</li>
<li><p>✅ GitHub vs Bitbucket</p>
</li>
<li><p>✅ Why enterprises choose GitLab</p>
</li>
<li><p>✅ GitLab SaaS vs Self-Managed</p>
</li>
<li><p>✅ Creating a GitLab account</p>
</li>
<li><p>✅ GitLab account verification process</p>
</li>
</ul>
<p>You now have a solid understanding of GitLab fundamentals and are ready to explore its practical features.</p>
<h2>👨‍💻 About the Author</h2>
<p><strong>Hi, I'm Apurv Gujjar</strong>, a DevOps Engineer passionate about Cloud, AWS, Kubernetes, Docker, Terraform, GitLab, and Infrastructure Automation.</p>
<p>I share practical DevOps tutorials, real-world projects, certification guides, interview preparation, and cloud engineering best practices to help students and professionals build production-ready skills.</p>
<h2>📬 Connect With Me</h2>
<p>📧 <strong>Email:</strong> <a href="mailto:gujjarapurv181@gmail.com">gujjarapurv181@gmail.com</a></p>
<p>🌐 <strong>Portfolio:</strong> <a href="https://www.apurv-gujjar.co.in">https://www.apurv-gujjar.co.in</a></p>
<p>🐙 <strong>GitHub:</strong> <a href="https://github.com/ApurvGujjar07">https://github.com/ApurvGujjar07</a></p>
<p>💼 <strong>LinkedIn:</strong> <a href="https://www.linkedin.com/in/apurv-gujjar">https://www.linkedin.com/in/apurv-gujjar</a></p>
<p>If you enjoy DevOps, Cloud, and GitLab content, feel free to connect with me. I'm always happy to share knowledge and discuss modern cloud technologies.</p>
]]></content:encoded></item><item><title><![CDATA[📘 Terraform Series – Day 12]]></title><description><![CDATA[Secure State Management (S3 + DynamoDB Locking)
📝 Abstract
In Terraform, the state file (terraform.tfstate) is the most critical component that connects your configuration with real infrastructure. H]]></description><link>https://apurv-gujjar.me/terraform-series-day-12</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-12</guid><category><![CDATA[Terraform]]></category><category><![CDATA[S3]]></category><category><![CDATA[DynamoDB]]></category><category><![CDATA[AWS]]></category><category><![CDATA[ec2]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Thu, 23 Apr 2026 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/18577dea-0e19-4c08-9bda-19e986436b77.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Secure State Management (S3 + DynamoDB Locking)</p>
<h3>📝 Abstract</h3>
<p>In Terraform, the <strong>state file (</strong><code>terraform.tfstate</code><strong>)</strong> is the most critical component that connects your configuration with real infrastructure. However, storing it locally can lead to <strong>security risks, data loss, and team conflicts</strong>.</p>
<p>This blog explains how to securely manage Terraform state using <strong>AWS S3 (remote storage)</strong> and <strong>DynamoDB (state locking)</strong>, which is the industry-standard approach for production environments.</p>
<h3>🎯 Objectives</h3>
<p>After completing this blog, you will be able to:</p>
<ul>
<li><p>Understand Terraform state and its importance</p>
</li>
<li><p>Know why <code>.tfstate</code> should never be pushed to GitHub</p>
</li>
<li><p>Handle state loss scenarios</p>
</li>
<li><p>Understand state conflicts in team environments</p>
</li>
<li><p>Implement <strong>remote backend using S3 + DynamoDB</strong></p>
</li>
<li><p>Test state locking in real scenarios</p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 1: What is Terraform State?</h3>
</blockquote>
<p>Terraform maintains a file:</p>
<pre><code class="language-shell">terraform.tfstate
</code></pre>
<h3>🧠 This file stores:</h3>
<ul>
<li><p>Real infrastructure details</p>
</li>
<li><p>Resource IDs and attributes</p>
</li>
<li><p>Mapping between <strong>Terraform code ↔ AWS resources</strong></p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 2: Should You Push <code>.tfstate</code> to GitHub?</h3>
</blockquote>
<p>👉 ❌ <strong>NO — Never do this</strong></p>
<h3>⚠️ Why?</h3>
<p>Because it contains:</p>
<ul>
<li><p>Secrets (API keys, credentials)</p>
</li>
<li><p>Resource IDs</p>
</li>
<li><p>Internal infrastructure data</p>
</li>
</ul>
<p>👉 This can lead to <strong>security breaches</strong></p>
<h3>✅ Add to <code>.gitignore</code></h3>
<pre><code class="language-plaintext">*.tfstate
*.tfstate.backup
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f9ca2da1-694a-452f-b75c-327fe4943969.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<h3>🔷 Step 3: What if <code>.tfstate</code> is Deleted?</h3>
</blockquote>
<p>👉 Terraform loses tracking of infrastructure</p>
<h3>❗ Result:</h3>
<ul>
<li><p>Terraform thinks → <strong>nothing exists</strong></p>
</li>
<li><p>Next <code>terraform apply</code> → tries to recreate everything ❌</p>
</li>
</ul>
<h3>✅ Solutions:</h3>
<ul>
<li><p>Restore from backup (<code>.tfstate.backup</code>)</p>
</li>
<li><p>Use <strong>remote backend (best practice)</strong></p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 4: State Conflict (Very Important)</h3>
</blockquote>
<h3>🔹 Scenario:</h3>
<ul>
<li><p>Developer 1 → runs <code>terraform apply</code></p>
</li>
<li><p>Developer 2 → runs <code>terraform apply</code></p>
</li>
</ul>
<h3>❗ What Happens?</h3>
<ul>
<li><p>Both modify same state file</p>
</li>
<li><p>File gets overwritten or corrupted</p>
</li>
</ul>
<p>👉 This is called <strong>State Conflict</strong></p>
<blockquote>
<h3>🔷 Step 5: Solutions</h3>
</blockquote>
<p>❌ Local Shared State</p>
<ul>
<li><p>Not safe</p>
</li>
<li><p>Not scalable</p>
</li>
</ul>
<p>✅ Remote Backend (Best Practice)</p>
<p>Use:</p>
<ul>
<li><p><strong>S3 Bucket</strong> → Store state file</p>
</li>
<li><p><strong>DynamoDB</strong> → Lock state</p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 6: Architecture Flow</h3>
</blockquote>
<h3>🧠 Working:</h3>
<ol>
<li><p>Terraform stores state in <strong>S3</strong></p>
</li>
<li><p>Before update → checks <strong>DynamoDB</strong></p>
</li>
<li><p>If no lock → creates <code>LockID</code></p>
</li>
<li><p>While locked → ❌ no parallel execution</p>
</li>
<li><p>After completion → lock removed</p>
</li>
</ol>
<blockquote>
<h3>🔷 Step 7: Practical Implementation</h3>
</blockquote>
<h3>📁 Step 1: Create Project Folder</h3>
<pre><code class="language-shell">mkdir remote-infra
cd remote-infra
</code></pre>
<h3>📄 Step 2: Create Files</h3>
<pre><code class="language-shell">touch provider.tf terraform.tf s3.tf dynamodb.tf
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/95ff2b54-9ad6-45ba-8c97-d8d6ee55591e.png" alt="" style="display:block;margin:0 auto" />

<h3>🔧 Step 3: Provider Configuration</h3>
<pre><code class="language-shell">provider "aws" {
  region = "us-east-2"
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ec14a391-0f11-4aec-a469-7ff1c714146d.png" alt="" style="display:block;margin:0 auto" />

<h3>📦 Step 4: Terraform Block</h3>
<pre><code class="language-plaintext">terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&gt; 6.0"
    }
  }
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0bf7d1ca-cff2-4e7d-aa40-626e7c823da9.png" alt="" style="display:block;margin:0 auto" />

<h3>🪣 Step 5: Create S3 Bucket</h3>
<pre><code class="language-shell">resource "random_id" "suffix" {
  byte_length = 2
}

resource "aws_s3_bucket" "remote_s3" {
  bucket = "dev-tf-state-${random_id.suffix.hex}"

  tags = {
    Name        = "tf-state-bucket"
    Environment = "dev"
  }
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c32db342-0532-4b1a-9ebc-cac1a9754c06.png" alt="" style="display:block;margin:0 auto" />

<h3>🔐 Step 6: Create DynamoDB Table</h3>
<pre><code class="language-shell">resource "aws_dynamodb_table" "state_lock" {
  name         = "apurv-table"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }

  tags = {
    Name        = "apurv-table"
    Environment = "Dev"
  }
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/42fad633-215c-4699-8212-91d291107ab4.png" alt="" style="display:block;margin:0 auto" />

<h3>🔑 Step 7: IAM Permissions</h3>
<p>Ensure your AWS user/role has:</p>
<ul>
<li><p>S3 Full Access</p>
</li>
<li><p>DynamoDB Full Access</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b7cafcc8-0932-435b-b8d2-e61e47043507.png" alt="" style="display:block;margin:0 auto" />

<h3>🔷 Step 8: Run Terraform</h3>
<pre><code class="language-plaintext">terraform init
terraform validate
terraform plan
terraform apply
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6d55e7d3-85df-4359-b09d-71a9668ea65d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0d19a287-0584-4135-84ca-b61f7ba990be.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/43568c4f-3193-4db9-8507-77b16745cab5.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e147f25c-965a-4484-ba5e-62fc163fd52d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d65b78b0-62b3-430a-bfb1-216f25a9d70e.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<h3>🔷 Step 9: Configure Remote Backend</h3>
</blockquote>
<p>Now go to your <strong>main project folder</strong> and update:</p>
<pre><code class="language-shell">terraform {
  backend "s3" {
    bucket         = "bucket&lt;name&gt;"
    key            = "terraform.tfstate"
    region         = "us-east-2"
    dynamodb_table = "apurv-table"
  }
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/10e60056-70d3-445e-965b-5b907994558a.png" alt="" style="display:block;margin:0 auto" />

<h3>🔄 Reinitialize</h3>
<pre><code class="language-shell">terraform init
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0e6c643b-ea9f-41f6-ae05-577615cf41c1.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<h3>🔷 Step 10: Remove Local State</h3>
</blockquote>
<pre><code class="language-shell">rm terraform.tfstate*
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/111892e4-2da2-4229-9f2a-500e22a3b859.png" alt="" style="display:block;margin:0 auto" />

<h3>✅ Verify Remote State</h3>
<pre><code class="language-shell">terraform state list
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/8dbcfc21-d389-4fdf-93aa-a5befc0667b6.png" alt="" style="display:block;margin:0 auto" />

<p>👉 Resources will still appear<br />✔ Because state is now stored in <strong>S3</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f468ffcb-cce3-413b-af5b-2db77e0d0519.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<h3>🔷 Step 11: Test State Locking</h3>
</blockquote>
<h3>Terminal 1:</h3>
<pre><code class="language-plaintext">terraform apply
</code></pre>
<h3>Terminal 2:</h3>
<pre><code class="language-plaintext">terraform apply
</code></pre>
<h3>❗ Result:</h3>
<ul>
<li><p>Terminal 2 → ❌ blocked / waits</p>
</li>
<li><p>Reason → Lock exists in DynamoDB</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/7b5f6de2-8a48-4cec-8aa4-bc055307f019.png" alt="" style="display:block;margin:0 auto" />

<h3>✔ After Completion:</h3>
<ul>
<li><p>Lock is removed</p>
</li>
<li><p>Second execution proceeds</p>
</li>
<li><p>After testing all the things you can destroy your resources</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e01d21d3-ae83-414a-ac13-684cacdef7d1.png" alt="" style="display:block;margin:0 auto" />

<h3>🚀 Conclusion</h3>
<ul>
<li><p>Terraform state is <strong>critical for infrastructure tracking</strong></p>
</li>
<li><p>Never store state locally in production</p>
</li>
<li><p>Use <strong>S3 for storage + DynamoDB for locking</strong></p>
</li>
<li><p>Prevents:</p>
<ul>
<li><p>Data loss</p>
</li>
<li><p>State conflicts</p>
</li>
<li><p>Security risks</p>
</li>
</ul>
</li>
</ul>
<h3><strong>👨‍💻 About the Author</strong></h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘 Terraform Series – Day 11]]></title><description><![CDATA[Terraform State Management & Import
📝 Abstract
Terraform works by maintaining a record of infrastructure in a state file. This state file acts as the bridge between your Terraform configuration and r]]></description><link>https://apurv-gujjar.me/terraform-series-day-11</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-11</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Wed, 22 Apr 2026 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/bcad90c1-b758-4551-96ec-b8e32bc18b81.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Terraform State Management &amp; Import</p>
<h3>📝 Abstract</h3>
<p>Terraform works by maintaining a record of infrastructure in a <strong>state file</strong>. This state file acts as the bridge between your Terraform configuration and real-world resources (like AWS EC2, Security Groups, etc.).</p>
<p>In this blog, we will understand how Terraform manages state, why it is important, how to handle state manually, and how to import existing resources into Terraform.</p>
<h3>🎯 Objectives</h3>
<p>After completing this blog, you will be able to:</p>
<ul>
<li><p>Understand what <strong>Terraform state</strong> is</p>
</li>
<li><p>Know why state management is important</p>
</li>
<li><p>Sync Terraform state with real infrastructure</p>
</li>
<li><p>Use important <strong>state commands</strong></p>
</li>
<li><p>Understand <code>terraform import</code></p>
</li>
<li><p>Handle real-world interview scenarios</p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 1: What is Terraform State?</h3>
</blockquote>
<p>Terraform maintains a file called:</p>
<pre><code class="language-shell">terraform.tfstate
</code></pre>
<hr />
<h3>🧠 This file stores:</h3>
<ul>
<li><p>All created resources (EC2, Security Groups, etc.)</p>
</li>
<li><p>Current status of resources (running, stopped, IDs, etc.)</p>
</li>
<li><p>Mapping between <strong>Terraform config ↔ real infrastructure</strong></p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 2: Why State Management is Required</h3>
</blockquote>
<p>Terraform uses the state file to:</p>
<ul>
<li><p>Know what resources are already created ✅</p>
</li>
<li><p>Track infrastructure changes ✅</p>
</li>
<li><p>Avoid recreating resources unnecessarily ✅</p>
</li>
<li><p>Compare <strong>desired state vs actual state</strong> ✅</p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 3: Important Scenario (Very Important)</h3>
</blockquote>
<h3>🔹 Situation:</h3>
<ul>
<li><p>EC2 is <strong>running</strong> in Terraform state</p>
</li>
<li><p>You manually <strong>stop it from AWS Console</strong></p>
</li>
</ul>
<h3>❓ Will Terraform automatically update state?</h3>
<p>👉 ❌ NO</p>
<p>Terraform does not auto-detect manual changes.</p>
<blockquote>
<h3>🔷 Step 4: How to Sync State</h3>
</blockquote>
<p>To update Terraform state:</p>
<pre><code class="language-shell">terraform refresh
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ba441df5-cb1c-477b-a0d9-b7cbf0d3ec1f.png" alt="" style="display:block;margin:0 auto" />

<p>OR</p>
<pre><code class="language-shell">terraform apply
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/db04399c-de37-4aff-9cb6-b27b3cdee1c8.png" alt="" style="display:block;margin:0 auto" />

<h3>✔ Result</h3>
<ul>
<li><p>Terraform reads real infrastructure</p>
</li>
<li><p>Updates state file</p>
</li>
</ul>
<p>👉 Example:<br /><code>running → stopped</code></p>
<blockquote>
<h3>🔷 Step 5: State Management Commands</h3>
</blockquote>
<h3>1️⃣ List All Resources</h3>
<pre><code class="language-shell">terraform state list
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b801175e-fbac-40a5-baae-636b1ccf0361.png" alt="" style="display:block;margin:0 auto" />

<h3>2️⃣ Show Resource Details</h3>
<pre><code class="language-shell">terraform state show aws_instance.my_instance
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/34de2843-92b5-4e45-b83e-0831968f56a3.png" alt="" style="display:block;margin:0 auto" />

<h3>3️⃣ Remove Resource from State</h3>
<pre><code class="language-shell">terraform state rm aws_key_pair.my_key
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/78c5667f-7b1b-47c0-96f5-e20bd9e7ab3b.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<h3>🔷 Step 6: Important Interview Question</h3>
</blockquote>
<h3>❓ What happens if you run:</h3>
<pre><code class="language-shell">terraform state rm aws_key_pair.my_key
</code></pre>
<h3>🔥 Answer</h3>
<ul>
<li><p>❌ Resource is NOT deleted from AWS</p>
</li>
<li><p>✅ Only removed from Terraform state</p>
</li>
</ul>
<p>👉 The actual resource still exists in AWS</p>
<blockquote>
<h3>🔷 Step 7: How to Restore Resource (Import Back)</h3>
</blockquote>
<p>If you removed resource from state by mistake:</p>
<pre><code class="language-shell">terraform import aws_key_pair.my_key &lt;key-Name-in aws&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ce701b9f-e7ba-48db-909d-d299c237cd2c.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d7b06138-3d2e-4c0f-b78c-26af4c75e4b3.png" alt="" style="display:block;margin:0 auto" />

<h3>✔ Result</h3>
<ul>
<li><p>Resource is added back to Terraform state</p>
</li>
<li><p>Terraform starts managing it again</p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 8: Importing Existing EC2 Instance</h3>
</blockquote>
<h3>🧩 Step 1: Create Resource Block</h3>
<pre><code class="language-shell">resource "aws_instance" "my_instance" {
  ami           = "ami-xxxx"   # placeholder
  instance_type = "t2.micro"
}
</code></pre>
<p>👉 Values can be temporary/dummy</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/4a01b747-8661-421b-be46-d752e9fdb3e2.png" alt="" style="display:block;margin:0 auto" />

<h3>🧩 Step 2: Run Import Command</h3>
<pre><code class="language-shell">terraform import aws_instance.my_instance &lt;instance-id&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/821a4e6c-bfa5-47a2-a4c3-7843f9358a70.png" alt="" style="display:block;margin:0 auto" />

<p>👉 Example:</p>
<pre><code class="language-shell">terraform import aws_instance.demo-instance i-1234567890abcdef0
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/2fd4e194-a299-4d99-ae95-15d5f2531051.png" alt="" style="display:block;margin:0 auto" />

<h3>🧩 Step 3: Verify</h3>
<pre><code class="language-shell">terraform state show aws_instance.my_instance
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a6a5d1a1-d2c0-44be-b905-4194d1ddabe9.png" alt="" style="display:block;margin:0 auto" />

<h3>🧩 Step 4: Fix Configuration (Important)</h3>
<p>After import:</p>
<pre><code class="language-shell">terraform plan
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e888053d-a432-4e1a-8523-86dd497dcacc.png" alt="" style="display:block;margin:0 auto" />

<p>👉 Then:</p>
<ul>
<li><p>Update <code>.tf</code> file with <mark class="bg-yellow-200 dark:bg-yellow-500/30"> correct values</mark></p>
</li>
<li><p>Match actual AWS configuration</p>
</li>
</ul>
<h3>⚠️ Important Notes</h3>
<ul>
<li><p>Import updates <strong>only state</strong>, not Terraform code</p>
</li>
<li><p>You must manually update <code>.tf</code> files</p>
</li>
<li><p>If configuration does not match → Terraform will try to modify resource</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/11b3ebfa-509e-4b2b-919d-ee65e1e0b554.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ba99f752-a725-425c-87bd-0e32e4cd309d.png" alt="" style="display:block;margin:0 auto" />

<h3>🚀 Conclusion</h3>
<ul>
<li><p>Terraform state is the <strong>core of infrastructure tracking</strong></p>
</li>
<li><p>Manual changes are <strong>not auto-detected</strong></p>
</li>
<li><p>Use <code>terraform refresh/apply</code> to sync</p>
</li>
<li><p><code>terraform state</code> commands help manage resources</p>
</li>
<li><p><code>terraform import</code> is useful for existing infrastructure</p>
</li>
</ul>
<h3><strong>👨‍💻 About the Author</strong></h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘 Terraform Series – Day 10]]></title><description><![CDATA[Conditional Expressions (Ternary Operator)
📝 Abstract
In real-world DevOps projects, infrastructure often needs to behave differently based on environments such as development, staging, and productio]]></description><link>https://apurv-gujjar.me/terraform-series-day-10</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-10</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Tue, 21 Apr 2026 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/37248cf7-327c-4b47-a85f-772bad5e01cb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Conditional Expressions (Ternary Operator)</h3>
<h3>📝 Abstract</h3>
<p>In real-world DevOps projects, infrastructure often needs to behave differently based on environments such as <strong>development, staging, and production</strong>. Instead of writing separate configurations, Terraform provides <strong>conditional expressions (ternary operators)</strong> to dynamically assign values.</p>
<p>This blog explains how to use conditional expressions in Terraform to make infrastructure more <strong>flexible, reusable, and environment-aware</strong>.</p>
<h3>🎯 Objectives</h3>
<p>After completing this blog, you will be able to:</p>
<ul>
<li><p>Understand <strong>conditional expressions in Terraform</strong></p>
</li>
<li><p>Use the <strong>ternary operator syntax</strong></p>
</li>
<li><p>Apply conditions in real resources (EC2 example)</p>
</li>
<li><p>Configure infrastructure based on environment (<code>dev</code>, <code>prod</code>)</p>
</li>
<li><p>Test and verify conditional logic</p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 1: What is a Conditional Expression?</h3>
</blockquote>
<p>A <strong>conditional expression</strong> (also called a <strong>ternary operator</strong>) is used to assign values based on a condition.</p>
<p>🧠 Syntax</p>
<pre><code class="language-shell">condition ? true_value : false_value
</code></pre>
<p>👉 Meaning</p>
<ul>
<li><p>If condition is <strong>true</strong> → use <code>true_value</code></p>
</li>
<li><p>If condition is <strong>false</strong> → use <code>false_value</code></p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 2: Real Example (EC2 Root Volume)</h3>
</blockquote>
<pre><code class="language-shell">root_block_device {
  volume_size = var.env == "prod" ? 20 : var.ec2_root_default_storage_size
  volume_type = "gp3"
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6ef10499-cf5f-4563-a641-63ca3fa8b0d7.png" alt="" style="display:block;margin:0 auto" />

<h3>🧠 Logic Explained</h3>
<ul>
<li><p>If <code>env = "prod"</code> → volume size = <strong>20 GB</strong></p>
</li>
<li><p>Else → volume size = <strong>default value (10 GB)</strong></p>
</li>
</ul>
<p>👉 This helps in <strong>automatically adjusting infrastructure</strong> based on environment</p>
<blockquote>
<h3>🔷 Step 3: Variables Used</h3>
</blockquote>
<pre><code class="language-shell">variable "env" {
  default = "dev" or # "prod"
  type    = string
}

variable "ec2_root_default_storage_size" {
  default = 10
  type    = number
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a2aba3bf-60a5-4c56-8fab-8219eb828042.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<h3>🔷 Step 4: Testing the Conditional Expression</h3>
</blockquote>
<h3>✅ Case 1: Production Environment</h3>
<pre><code class="language-shell">env = "prod"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/61b9d164-e794-45c0-9c32-fc205de80981.png" alt="" style="display:block;margin:0 auto" />

<h3>🔍 Output Behavior</h3>
<ul>
<li><p>Condition → <code>true</code></p>
</li>
<li><p>Volume Size → <strong>20 GB</strong></p>
</li>
</ul>
<p>✔ Instance will be created with <strong>larger storage (production-ready)</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/fc7bb608-5e48-4bb1-aafa-655be39812ec.png" alt="" style="display:block;margin:0 auto" />

<h3>✅ Case 2: Development Environment</h3>
<pre><code class="language-shell">env = "dev"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9e951d97-5aec-488d-8998-8e030e3d47f1.png" alt="" style="display:block;margin:0 auto" />

<p>🔍 Output Behavior</p>
<ul>
<li><p>Condition → <code>false</code></p>
</li>
<li><p>Volume Size → <strong>10 GB</strong></p>
</li>
</ul>
<p>✔ Instance will be created with <strong>default storage (cost-saving)</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/5f0f3030-16d9-470a-9a04-b8f706f4bb1a.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<h3>🔷 Step 5: Why Use Conditional Expressions?</h3>
</blockquote>
<p>Using conditional expressions helps in:</p>
<ul>
<li><p>Reducing duplicate code</p>
</li>
<li><p>Managing multiple environments easily</p>
</li>
<li><p>Improving infrastructure flexibility</p>
</li>
<li><p>Writing clean and reusable Terraform code</p>
</li>
</ul>
<blockquote>
<h3>🔷 Step 6: Best Practices</h3>
</blockquote>
<ul>
<li><p>Use conditions for <strong>environment-based configurations</strong></p>
</li>
<li><p>Keep values <strong>simple and readable</strong></p>
</li>
<li><p>Avoid overly complex nested conditions</p>
</li>
<li><p>Combine with variables for better control</p>
</li>
</ul>
<h3>🚀 Conclusion</h3>
<ul>
<li><p>Conditional expressions allow <strong>dynamic value assignment</strong></p>
</li>
<li><p>Syntax is simple: <code>condition ? true_value : false_value</code></p>
</li>
<li><p>Useful for handling <strong>prod vs dev differences</strong></p>
</li>
<li><p>Makes Terraform code <strong>clean, scalable, and reusable</strong></p>
</li>
</ul>
<h3><strong>👨‍💻 About the Author</strong></h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘 Terraform Series – Day 9]]></title><description><![CDATA[Meta Arguments: count vs for_each with Output
📝 Abstract
In Terraform, managing multiple resources efficiently is a common requirement in real-world DevOps projects. While creating multiple instances]]></description><link>https://apurv-gujjar.me/terraform-series-day-9</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-9</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[k8s]]></category><category><![CDATA[User Interface]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Mon, 20 Apr 2026 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/7c837f24-cb3c-40d6-bd3e-2638a82dc46c.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Meta Arguments: <code>count</code> vs <code>for_each</code> with Output</p>
<h3>📝 Abstract</h3>
<p>In Terraform, managing multiple resources efficiently is a common requirement in real-world DevOps projects. While creating multiple instances may seem straightforward, choosing the right approach can significantly impact scalability, flexibility, and maintainability.</p>
<p>This blog explores <strong>Terraform meta arguments</strong>, specifically <code>count</code> and <code>for_each</code>, and demonstrates how they behave differently when creating multiple resources. It also covers how outputs change based on these approaches and when to use <code>depends_on</code> for explicit dependencies.</p>
<h3>🎯 Objectives</h3>
<p>After completing this blog, you will be able to:</p>
<ul>
<li><p>Understand what <strong>meta arguments</strong> are in Terraform</p>
</li>
<li><p>Create multiple resources using <code>count</code></p>
</li>
<li><p>Identify limitations of <code>count</code></p>
</li>
<li><p>Use <code>for_each</code> for better flexibility</p>
</li>
<li><p>Handle outputs correctly for both approaches</p>
</li>
<li><p>Understand the use of <code>depends_on</code></p>
</li>
</ul>
<h3>🔷 Step 1: Understanding Meta Arguments</h3>
<p>Meta arguments are <strong>special Terraform keywords</strong> that control resource behavior.</p>
<p>Common Meta Arguments:</p>
<ul>
<li><p><code>count</code></p>
</li>
<li><p><code>for_each</code></p>
</li>
<li><p><code>depends_on</code></p>
</li>
<li><p><code>lifecycle</code></p>
</li>
</ul>
<p>👉 In this tutorial, we focus on:</p>
<ul>
<li><p><code>count</code></p>
</li>
<li><p><code>for_each</code></p>
</li>
</ul>
<h3>🔷 Step 2: Creating Multiple Resources using <code>count</code></h3>
<p>✅ Code</p>
<pre><code class="language-shell">resource "aws_instance" "my_instance" {
  count         = 2
  ami           = var.ec2_ami_id
  instance_type = var.ec2_instance_type
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/4d8c6f34-136b-4c8f-a902-f63b594b0c8a.png" alt="" style="display:block;margin:0 auto" />

<h3>🔍 Explanation</h3>
<ul>
<li><p>Terraform creates <strong>2 EC2 instances</strong></p>
</li>
<li><p>Indexed as:</p>
</li>
</ul>
<pre><code class="language-shell">aws_instance.my_instance[0]
aws_instance.my_instance[1]
</code></pre>
<h3>🔷 Step 3: Output using <code>count</code></h3>
<pre><code class="language-shell">output "ec2_public_ip" {
  value = aws_instance.my_instance[*].public_ip
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/02777522-98d0-45cd-b23c-69ff5f4270d6.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1cee2ab4-6b35-4159-84ee-ebcdb04ecc9c.png" alt="" style="display:block;margin:0 auto" />

<h3>🧠 Concept</h3>
<ul>
<li><p><code>[*]</code> → <strong>Splat Expression</strong></p>
</li>
<li><p>Used to extract values from multiple resources</p>
</li>
</ul>
<h3>🔷 Step 4: Limitation of <code>count</code></h3>
<p>Using <code>count</code> has restrictions:</p>
<ul>
<li><p>Same configuration for all instances</p>
</li>
<li><p>Cannot assign:</p>
<ul>
<li><p>Different names ❌</p>
</li>
<li><p>Different instance types ❌</p>
</li>
</ul>
</li>
</ul>
<h3>🔷 Step 6: Using <code>for_each</code> (Better Approach)</h3>
<pre><code class="language-shell">resource "aws_instance" "my_instance" {
  for_each = {
    Apurv-1 = "t2.micro"
    Apurv-2 = "t2.medium"
  }

  ami           = var.ec2_ami_id
  instance_type = each.value

  tags = {
    Name = each.key
  }
}
</code></pre>
<h3>🧠 Explanation</h3>
<ul>
<li><p><code>each.key</code> → Instance Name</p>
</li>
<li><p><code>each.value</code> → Instance Type</p>
</li>
</ul>
<p>👉 Each instance becomes <strong>unique and configurable</strong></p>
<h3>🔷 apply terraform and check output</h3>
<pre><code class="language-shell">terraform apply 
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/73642d3d-e784-43be-b50d-c0960014e775.png" alt="" style="display:block;margin:0 auto" />

<h3>🔷 Step 7: Why Old Output Fails</h3>
<div>
<div>💡</div>
<div>In the above outputs, we get a list of Public IPs and DNS values. However, the issue is that Terraform only returns a <strong>list of values</strong>, and it does not clearly indicate which IP belongs to which instance.</div>
</div>

<p>❌ Old Code</p>
<pre><code class="language-shell">aws_instance.my_instance[*].public_ip
</code></pre>
<h3>❗ Reason</h3>
<ul>
<li><p><code>count</code> → returns <strong>list</strong></p>
</li>
<li><p><code>for_each</code> → returns <strong>map</strong></p>
</li>
</ul>
<p>👉 So <code>[*]</code> does not work here</p>
<h3>🔷 Step 8: Correct Output with <code>for_each</code></h3>
<p>✅ Public IP</p>
<pre><code class="language-shell">output "ec2_public_ip" {
  value = [
    for instance in aws_instance.my_instance :
    instance.public_ip
  ]
}
</code></pre>
<p>✅ Public DNS</p>
<pre><code class="language-shell">output "ec2_public_dns" {
  value = [
    for instance in aws_instance.my_instance :
    instance.public_dns
  ]
}
</code></pre>
<p>✅ Private IP</p>
<pre><code class="language-shell">output "ec2_private_ip" {
  value = [
    for instance in aws_instance.my_instance :
    instance.private_ip
  ]
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ce86207e-05e3-434a-a192-f81427ef383a.png" alt="" style="display:block;margin:0 auto" />

<h3>🔷 Step 9: Final Result</h3>
<p>After applying <code>for_each</code>:</p>
<ul>
<li><p>Different instance names ✅</p>
</li>
<li><p>Different instance types ✅</p>
</li>
<li><p>Correct outputs fetched ✅</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a2fbe1b6-a303-4db8-9277-9d58670ec226.png" alt="" style="display:block;margin:0 auto" />

<h3>🔷 Step 10: Understanding <code>depends_on</code></h3>
<p>✅ Definition</p>
<p><code>depends_on</code> is used to <strong>explicitly define dependencies</strong></p>
<p>⚙️ Example</p>
<pre><code class="language-shell">depends_on = [
  aws_security_group.my_groups,
  aws_key_pair.my_key
]
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/827a91ae-6586-416e-ab82-20d6b4af4997.png" alt="" style="display:block;margin:0 auto" />

<h3>🧠 When to Use</h3>
<ul>
<li><p>When Terraform <strong>cannot detect dependency automatically</strong></p>
</li>
<li><p>When using <strong>hardcoded values</strong></p>
</li>
<li><p>When dependencies are <strong>indirect</strong></p>
</li>
</ul>
<p>❌ When NOT to Use</p>
<pre><code class="language-shell">key_name = aws_key_pair.my_key.key_name
</code></pre>
<p>👉 Terraform automatically handles this (<strong>implicit dependency</strong>)</p>
<h3>🚀 Conclusion</h3>
<ul>
<li><p>Use <code>count</code> → for simple, identical resources</p>
</li>
<li><p>Use <code>for_each</code> → for flexible and scalable setups</p>
</li>
<li><p>Understand difference between <strong>list vs map outputs</strong></p>
</li>
<li><p>Use <code>depends_on</code> only when required</p>
</li>
</ul>
<h3><strong>👨‍💻 About the Author</strong></h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 8]]></title><description><![CDATA[Automating AWS EC2 Setup with Terraform and user_data
Welcome back to our Terraform journey. In infrastructure as code, setting up a server is just the beginning. After your EC2 instance is running, y]]></description><link>https://apurv-gujjar.me/terraform-series-day-8</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-8</guid><category><![CDATA[Terraform]]></category><category><![CDATA[Script]]></category><category><![CDATA[automation]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Mon, 13 Apr 2026 03:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/76ff913c-44c3-4825-aecc-f7c0a309e516.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Automating AWS EC2 Setup with Terraform and <code>user_data</code></p>
<p>Welcome back to our Terraform journey. In infrastructure as code, setting up a server is just the beginning. After your EC2 instance is running, you need to set it up, install what it needs, and start your apps. Doing this by hand goes against the idea of automation.</p>
<p>In this post, we will demonstrate how to completely automate your server bootstrapping process using Terraform and the AWS user_data feature.</p>
<h3>🎯 Objective</h3>
<p>By the end of this guide, you will learn how to automatically install and configure an Nginx web server on a newly provisioned AWS EC2 instance using a Terraform <code>user_data</code> script.</p>
<h3>🧩 Step 1: Understanding the Power of <code>user_data</code></h3>
<p><strong>The Problem with Manual Configuration</strong></p>
<p>Imagine you just used Terraform to spin up a fresh EC2 instance. Without an automation script, your next steps would look like this:</p>
<ol>
<li><p>SSH into the instance.</p>
</li>
<li><p>Manually run package updates.</p>
</li>
<li><p>Install Nginx.</p>
</li>
<li><p>Start the service.</p>
</li>
<li><p>Create a custom HTML page.</p>
</li>
</ol>
<p>This approach is <strong><mark class="bg-yellow-200 dark:bg-yellow-500/30">time-consuming</mark></strong><mark class="bg-yellow-200 dark:bg-yellow-500/30">, </mark> <strong><mark class="bg-yellow-200 dark:bg-yellow-500/30">prone to human error</mark></strong>, and most importantly, <strong><mark class="bg-yellow-200 dark:bg-yellow-500/30">not scalable</mark></strong><mark class="bg-yellow-200 dark:bg-yellow-500/30">.</mark> If you need to spin up 100 web servers behind a load balancer, logging into each one manually is impossible.</p>
<h3>The Solution: Bootstrap Scripts</h3>
<p>AWS provides a feature called <code>user_data</code> that allows you to pass a script to your instance at launch.</p>
<ul>
<li><p>✔️ <strong>Runs automatically</strong> the very first time the instance boots.</p>
</li>
<li><p>✔️ <strong>Fully automates</strong> software installation and configuration.</p>
</li>
<li><p>✔️ <strong>Scales infinitely</strong> across as many instances as you deploy.</p>
</li>
</ul>
<p><strong>In short:</strong> <code>user_data</code> is your EC2 bootstrapping engine.</p>
<h3>📄 Step 2: Create the Bootstrapping Script (<a href="http://nginx.sh"><code>nginx.sh</code></a>)</h3>
<p>First, we need to define the commands we want our server to run on startup. We will create a simple bash script that installs Nginx and creates a custom landing page.</p>
<p><strong>Create a new file named</strong> <a href="http://nginx.sh"><code>nginx.sh</code></a><strong>:3</strong></p>
<pre><code class="language-shell">touch nginx.sh
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/0670068c-a5ae-4fac-9025-ae97babb83a4.png" alt="" style="display:block;margin:0 auto" />

<p>Add the following content to the file:-</p>
<pre><code class="language-shell">#!/bin/bash

# Update package lists
sudo apt-get update

# Install Nginx silently (-y prevents the prompt)
sudo apt-get install nginx -y

# Start the Nginx service
sudo systemctl start nginx

# Enable Nginx to start automatically if the server reboots
sudo systemctl enable nginx

# Create a custom HTML landing page
echo "&lt;h1&gt; Terraform testing with scripting &lt;/h1&gt;" &gt; /var/www/html/index.html
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b4762218-23fb-4e3e-8a04-b44cfc7d2e7e.png" alt="" style="display:block;margin:0 auto" />

<h3>🔗 Step 3: Attach the Script in Terraform</h3>
<p>Now, we need to tell Terraform to pass this script to our EC2 instance during creation. We do this by utilizing the <code>file()</code> function within the <code>user_data</code> argument of our <code>aws_instance</code> resource.</p>
<p>O<strong>pen your</strong> <a href="http://ec2.tf"><code>ec2.tf</code></a> file and configure your instance block:-</p>
<pre><code class="language-shell">resource "aws_instance" "my_instance" {
  ami           = var.ec2_ami_id
  instance_type = var.ec2_instance_type

  # Attach your SSH key pair
  key_name = aws_key_pair.my_key.key_name

  # Attach the security group (make sure port 80 is open!)
  vpc_security_group_ids = [aws_security_group.my_groups.id]

  # Inject the bootstrap script here
  user_data = file("nginx.sh")

  # Define root storage
  root_block_device {
    volume_size = var.ec2_root_storage_size
    volume_type = "gp3"
  }

  tags = {
    Name = "terraform-ec2-nginx"
  }
}
</code></pre>
<div>
<div>💡</div>
<div>Note: Using <code>file("</code><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="http://nginx.sh" style="pointer-events:none"><code>nginx.sh</code></a><code>")</code> keeps your Terraform code clean by separating the bash logic from the HCL infrastructure definitions.</div>
</div>

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/7634a350-209b-4297-a02a-08aadbd0ff75.png" alt="" style="display:block;margin:0 auto" />

<h3>⚙️ Step 4: Execute the Pipeline</h3>
<p>With the script created and Terraform configured, it's time to deploy. Run the following commands in your terminal:</p>
<p>Bash</p>
<pre><code class="language-plaintext">terraform init
terraform apply -auto-approve
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e8c3cb46-5109-4f25-a62d-c03461ef3ed7.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e8221ec0-5081-4de6-a233-8a42dc4a22f9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/07eeff41-0c6b-42fd-acca-b2348385ce79.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f6684dfd-0b58-48a1-89e4-5b441c90927e.png" alt="" style="display:block;margin:0 auto" />

<h3>What happens internally?</h3>
<p>Once you hit apply, an elegant automated workflow kicks off:</p>
<ol>
<li><p><strong>Infrastructure Provisioned:</strong> Terraform calls the AWS API to launch a new EC2 instance.</p>
</li>
<li><p><strong>Script Passed:</strong> The contents of <a href="http://nginx.sh"><code>nginx.sh</code></a> are passed to the instance metadata.</p>
</li>
<li><p><strong>Bootstrapping Execution:</strong> As the EC2 instance boots up, the OS executes the script as the <code>root</code> user.</p>
</li>
<li><p><strong>App Deployed:</strong> Packages are updated, Nginx is installed, the service is started, and your custom HTML page is generated.</p>
</li>
</ol>
<p>Within minutes, you can grab the public IP of your new EC2 instance, paste it into your browser, and see your custom HTML page—zero SSH required.</p>
<h3><mark class="bg-yellow-200 dark:bg-yellow-500/30">🧪 Testing: Verify NGINX on EC2 Instance</mark></h3>
<p>After provisioning the EC2 instance using <strong>Terraform</strong>, we need to test whether <strong>NGINX is properly installed and running</strong>.</p>
<h3>🔹 Step 1: Connect to EC2 via SSH</h3>
<pre><code class="language-shell">ssh -i "your-key.pem" ubuntu@&lt;EC2-PUBLIC-IP&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/8c3eb8a8-a3c5-4bee-9ef7-0ffc66afec7b.png" alt="" style="display:block;margin:0 auto" />

<p>✔ Replace:</p>
<ul>
<li><p><code>your-key.pem</code> → your private key</p>
</li>
<li><p><code>&lt;EC2-PUBLIC-IP&gt;</code> → instance public IP</p>
</li>
</ul>
<h3>🔹 Step 2: Check NGINX Status</h3>
<pre><code class="language-shell">sudo systemctl status nginx
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9f427d6c-204c-43e2-9efd-10dad93d2728.png" alt="" style="display:block;margin:0 auto" />

<p>✔ Expected Output:</p>
<ul>
<li><p><code>active (running)</code> → ✅ NGINX is working</p>
</li>
<li><p><code>inactive / failed</code> → ❌ issue needs fixing</p>
</li>
</ul>
<h3>🔹 Step 3: Test via Browser</h3>
<p>Open your browser and hit:</p>
<pre><code class="language-shell">http://&lt;EC2-PUBLIC-IP&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/619516b2-c1aa-48a3-9402-a3503de4e255.png" alt="" style="display:block;margin:0 auto" />

<p>✔ Expected:</p>
<ul>
<li>Default <strong>NGINX Welcome Page</strong></li>
</ul>
<h3>🔹 Step 5: Test via Curl (CLI Testing)</h3>
<pre><code class="language-plaintext">curl http://localhost
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d93d1b5b-90a8-4868-96d5-2022836b4e65.png" alt="" style="display:block;margin:0 auto" />

<p>OR from your local system:</p>
<pre><code class="language-plaintext">curl http://&lt;EC2-PUBLIC-IP&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/012ae3eb-d89e-4c62-b350-e0105478f032.png" alt="" style="display:block;margin:0 auto" />

<p>✔ If HTML response comes → ✅ Server is working</p>
<h3>🔹 Step 6: Check Port 80 (Important for DevOps)</h3>
<pre><code class="language-plaintext">sudo netstat -tulpn | grep :80
</code></pre>
<p>OR</p>
<pre><code class="language-plaintext">sudo ss -tulpn | grep :80
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/cbf8c0a4-7034-4ca3-991d-02050306b8fc.png" alt="" style="display:block;margin:0 auto" />

<p>✔ Confirms:</p>
<ul>
<li>NGINX is listening on port 80</li>
</ul>
<h3>💡 Key Takeaways</h3>
<ul>
<li><p><strong>No More Manual SSH:</strong> Bootstrapping completely eliminates the need to manually configure infrastructure after it is provisioned.</p>
</li>
<li><p><strong>Separation of Concerns:</strong> By using the <code>file()</code> function, you keep your shell scripts separate from your Terraform code, making both easier to maintain.</p>
</li>
<li><p><strong>Idempotency and Scale:</strong> A script guarantees that every server you provision will be configured exactly the same way, every single time.</p>
</li>
</ul>
<h3><strong>👨‍💻 About the Author</strong></h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 7]]></title><description><![CDATA[Variables & Outputs (Make Your Code Smart 🔥)
In real-world DevOps, writing flexible and reusable code is very important.Today, we will learn how to use Variables and Outputs in Terraform to make our ]]></description><link>https://apurv-gujjar.me/terraform-series-day-7</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-7</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[k8s]]></category><category><![CDATA[ec2]]></category><category><![CDATA[vpc]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 12 Apr 2026 03:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/619fdeca-813e-4244-896f-b0ad5b210c03.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Variables &amp; Outputs (Make Your Code Smart 🔥)</p>
<p>In real-world DevOps, writing flexible and reusable code is very important.<br />Today, we will learn how to use <strong>Variables</strong> and <strong>Outputs</strong> in Terraform to make our infrastructure clean, dynamic, and production-ready.</p>
<p>Till now, we were writing Terraform code…<br />but there was one problem 👇</p>
<p>👉 <strong>Everything was hardcoded</strong></p>
<p>And in real DevOps, <mark class="bg-yellow-200 dark:bg-yellow-500/30">hardcoding = BIG mistake</mark> ❌</p>
<p>So today we fix that 💡</p>
<h3>🧩 Step 1: The Real Problem</h3>
<p>Imagine this:</p>
<pre><code class="language-shell">instance_type = "t2.micro"
</code></pre>
<p>Looks simple… but 👇</p>
<p>❌ Want to upgrade instance? Change everywhere</p>
<p>❌ Want reuse? Not possible</p>
<p>❌ Working in team? Becomes messy</p>
<p>👉 Basically: Not scalable</p>
<h3>💡 Step 2: The Smart Solution → Variables</h3>
<p>Instead of fixing values in code, we use <strong>variables</strong></p>
<p>Think like this:<br />👉 “Keep values separate, keep code clean”</p>
<h3>✔ Why Variables?</h3>
<ul>
<li><p>Change once → Apply everywhere</p>
</li>
<li><p>Clean &amp; readable code</p>
</li>
<li><p>Reusable infrastructure</p>
</li>
<li><p>Industry-level practice</p>
</li>
</ul>
<p>📌 <strong>In short:</strong><br />Variables = Flexibility + Clean Code + DevOps Standard</p>
<h3>📄 Step 3: Create <a href="http://variables.tf"><code>variables.tf</code></a></h3>
<pre><code class="language-shell">variable "ec2_instance_type" {
  default = "t2.micro"
  type    = string
}

variable "ec2_root_storage_size" {
  default = 10
  type    = number
}

variable "ec2_ami_id" {
  default = "ami-0cb91c7de36eed2cb"
  type    = string
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6051ea1a-7882-46e1-93af-4f09f089883f.png" alt="" style="display:block;margin:0 auto" />

<p>🧠 Simple Understanding:</p>
<ul>
<li><p><code>variable</code> → variable name</p>
</li>
<li><p><code>default</code> → default value</p>
</li>
<li><p><code>type</code> → data type</p>
</li>
</ul>
<p>👉 Values are now separated from the main code ✅</p>
<h3>🔗 Step 4: Use Variables in <a href="http://ec2.tf"><code>ec2.tf</code></a></h3>
<p>Now the real magic 🔥</p>
<pre><code class="language-shell"># Create Key Pair
resource "aws_key_pair" "my_key" {
  key_name   = "terra-key-aws"
  public_key = file("terra-key-aws.pub")
}


# Default VPC
resource "aws_default_vpc" "default" {}

# Security Group
resource "aws_security_group" "my_groups" {
  name        = "my-group"
  description = "Security group for EC2"
  vpc_id      = aws_default_vpc.default.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow SSH"
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow HTTP"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow all outbound"
  }

  tags = {
    Name = "automate-sg"
  }
}

# EC2 Instance
resource "aws_instance" "my_instance" {
  ami                    = var.ec2_ami_id
  instance_type          = var.ec2_instance_type
  key_name               = aws_key_pair.my_key.key_name
  vpc_security_group_ids = [aws_security_group.my_groups.id]

  root_block_device {
    volume_size = var.ec2_root_storage_size
    volume_type = "gp3"
  }

  tags = {
    Name = "terra-ec2"
  }
}
</code></pre>
<p>⚡ Important Line:</p>
<pre><code class="language-shell">var.&lt;variable_name&gt;
</code></pre>
<p>👉 Example:</p>
<pre><code class="language-shell">var.ec2_instance_type
</code></pre>
<h3>🔄 Step 5: Real Power of Variables</h3>
<p>Before:</p>
<pre><code class="language-plaintext">instance_type = "t2.micro"
</code></pre>
<p>After:</p>
<pre><code class="language-plaintext">default = "t3.micro"
</code></pre>
<p>✔ Change in one place</p>
<p>✔ Applied everywhere automatically</p>
<p>🔥 That’s the power</p>
<h3>📤 Step 6: Now Let’s Talk About Outputs</h3>
<p>Deployment is done… but now 👇</p>
<p>👉 How do you get EC2 Public IP?</p>
<h3>😓 Problem</h3>
<p>❌ You have to manually check AWS Console</p>
<h3>💡 Solution → Outputs</h3>
<p>Terraform will show it directly 🔥</p>
<h3>📄 Step 7: Create <a href="http://outputs.tf"><code>outputs.tf</code></a></h3>
<pre><code class="language-shell">output "ec2_public_ip" {
  value = aws_instance.my_instance.public_ip
}

output "ec2_public_dns" {
  value = aws_instance.my_instance.public_dns
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/5ea76f21-8d21-40ba-8169-6d35579afa17.png" alt="" style="display:block;margin:0 auto" />

<h3>🧠 What Happens Now?</h3>
<p>When you run:</p>
<pre><code class="language-plaintext">terraform apply
</code></pre>
<p>👉 At the end, Terraform shows:</p>
<p>✔ Public IP</p>
<p>✔ Public DNS</p>
<p>Directly in terminal 🎯</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/804365ec-f053-449e-95fc-2dbdb35ca982.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>👨‍💻 About the Author</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 6]]></title><description><![CDATA[🎯 Objective
In this hands-on, we will:

Generate SSH key

Create key pair using Terraform

Configure VPC & Security Group

Launch EC2 instance

Connect via SSH

Clean up resources


👉 This is your f]]></description><link>https://apurv-gujjar.me/terraform-series-day-6</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-6</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[k8s]]></category><category><![CDATA[GCP]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sat, 11 Apr 2026 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1ab8437e-acd3-473c-b41e-8aede6e960fb.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>🎯 Objective</h3>
<p>In this hands-on, we will:</p>
<ul>
<li><p>Generate SSH key</p>
</li>
<li><p>Create key pair using Terraform</p>
</li>
<li><p>Configure VPC &amp; Security Group</p>
</li>
<li><p>Launch EC2 instance</p>
</li>
<li><p>Connect via SSH</p>
</li>
<li><p>Clean up resources</p>
</li>
</ul>
<p>👉 This is your <strong>first real-world Terraform task</strong></p>
<h3>🧩 Step 1: Generate SSH Key</h3>
<pre><code class="language-shell">ssh-keygen
</code></pre>
<p>✔ This creates:</p>
<ul>
<li><p><code>terra-key-aws</code>→ Private key</p>
</li>
<li><p><a href="http://terra-key-ec2.pub"><code>terra-key-ec2.pub</code></a> → Public key</p>
</li>
</ul>
<p>👉 We will use this to access EC2</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/54b6780c-ca45-4254-8db3-9424d6f991fd.png" alt="" style="display:block;margin:0 auto" />

<h3>📄 Step 2: Create Terraform File</h3>
<pre><code class="language-shell">touch ec2.tf
</code></pre>
<p>🧱 Step 3: Add Terraform Code</p>
<pre><code class="language-shell"># Create Key Pair
resource "aws_key_pair" "my_key" {
  key_name   = "terra-key-aws"
  public_key = file("terra-key-aws.pub")
}


# Default VPC
resource "aws_default_vpc" "default" {}

# Security Group
resource "aws_security_group" "my_groups" {
  name        = "my-group"
  description = "Security group for EC2"
  vpc_id      = aws_default_vpc.default.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow SSH"
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow HTTP"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow all outbound"
  }

  tags = {
    Name = "automate-sg"
  }
}

# EC2 Instance
resource "aws_instance" "my_instance" {
  ami                    = "ami-0cb91c7de36eed2cb"
  instance_type          = "t2.micro"
  key_name               = aws_key_pair.my_key.key_name
  vpc_security_group_ids = [aws_security_group.my_groups.id]

  root_block_device {
    volume_size = 10
    volume_type = "gp3"
  }

  tags = {
    Name = "terra-ec2"
  }
}
</code></pre>
<h3>⚙️ Step 4: Initialize Terraform</h3>
<pre><code class="language-shell">terraform init
</code></pre>
<p>✔ Downloads AWS provider</p>
<p>✔ Prepares working directory</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c17141c1-2782-45b6-bfdc-062e48ac3ff8.png" alt="" style="display:block;margin:0 auto" />

<h3>✅ Step 5: Validate Configuration</h3>
<pre><code class="language-shell">terraform validate
</code></pre>
<p>✔ Ensures syntax is correct</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/76034d58-2af8-459e-8219-6435ba6f1611.png" alt="" style="display:block;margin:0 auto" />

<h3>📊 Step 6: Plan Execution</h3>
<pre><code class="language-shell">terraform plan
</code></pre>
<p>✔ Shows resources to be created:</p>
<ul>
<li><p>Key Pair</p>
</li>
<li><p>VPC</p>
</li>
<li><p>Security Group</p>
</li>
<li><p>EC2 Instance</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/60ce0fec-7f70-4ae4-83bf-d5a7fb4977d2.png" alt="" style="display:block;margin:0 auto" />

<h3>🚀 Step 7: Apply (Create Infrastructure)</h3>
<pre><code class="language-shell">terraform apply
</code></pre>
<p>👉 Type <code>yes</code> to confirm</p>
<h3>❌ Common Error: Not Authorized</h3>
<p>👉 Reason:</p>
<ul>
<li>IAM user does not have required permissions</li>
</ul>
<p>✔ Fix:</p>
<p>Go to <strong>AWS IAM → Attach Policy</strong></p>
<ul>
<li><p><code>AdministratorAccess</code> (easy way)</p>
<p>OR</p>
</li>
<li><p><code>EC2FullAccess</code></p>
</li>
<li><p><code>VPCFullAccess</code></p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/eefe5fda-8649-433a-840b-d4f56916dfe9.png" alt="" style="display:block;margin:0 auto" />

<h3>🖥 Step 8: Verify in AWS Console</h3>
<p>Go to EC2 Dashboard:</p>
<p>✔ Instance running<br />✔ Security group attached<br />✔ Key pair created</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/e2d2d40a-1d81-4172-b533-06b6a6c02d16.png" alt="" style="display:block;margin:0 auto" />

<h3>🔐 Step 9: Fix Key Permission</h3>
<pre><code class="language-shell">chmod 400 terra-key-aws
</code></pre>
<p>👉 Required before SSH</p>
<h3>🔗 Step 10: Connect to EC2</h3>
<pre><code class="language-shell">ssh -i terra-key-aws ubuntu@&lt;your-public-ip&gt;
</code></pre>
<p>👉 Now your server is live 🚀</p>
<h3>🧹 Step 11: Destroy Resources (IMPORTANT)</h3>
<pre><code class="language-shell">terraform destroy
</code></pre>
<p>👉 Prevent unnecessary AWS charges 💸</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/269447f8-0cf7-4332-a1f7-36eeb4b924ea.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>👨‍💻 About the Author</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 5]]></title><description><![CDATA[Terraform Providers, Resource Types & Naming
In today’s Terraform journey, I explored one of the most fundamental concepts that every DevOps engineer must understand Providers and Resource Naming Stru]]></description><link>https://apurv-gujjar.me/terraform-series-day-5</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-5</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Fri, 10 Apr 2026 03:40:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d9ea1363-bd2e-407b-9fd5-f6917ec0316b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Terraform Providers, Resource Types &amp; Naming</h3>
<p>In today’s Terraform journey, I explored one of the most fundamental concepts that every DevOps engineer must understand <strong>Providers and Resource Naming Structure</strong>.</p>
<p>These concepts are the backbone of Terraform because they define <strong>how Terraform communicates with real-world infrastructure</strong>.</p>
<h3>🧠 1. Understanding Terraform Resource Structure</h3>
<p>Every infrastructure component in Terraform is defined using a <strong>resource block</strong>.</p>
<p>📌 Syntax:</p>
<pre><code class="language-shell">resource "&lt;provider&gt;_&lt;resource_type&gt;" "&lt;name&gt;" {
  arguments
}
</code></pre>
<h3>📌 Example:</h3>
<pre><code class="language-shell">resource "aws_instance" "my_vm" {
  instance_type = "t2.micro"
}
</code></pre>
<h3>🔍 Deep Breakdown:</h3>
<ul>
<li><p><strong>provider (aws)</strong><br />→ Defines which platform you are using (AWS, GCP, Azure, etc.)</p>
</li>
<li><p><strong>resource_type (instance)</strong><br />→ Specifies what you want to create (VM, bucket, network, etc.)</p>
</li>
<li><p><strong>name (my_vm)</strong><br />→ A local identifier inside Terraform (you can name it anything)</p>
</li>
<li><p><strong>arguments</strong><br />→ Configuration details (size, region, OS, etc.)</p>
</li>
</ul>
<h3>⚡ Important Insight:</h3>
<p>👉 Terraform does <strong>not identify resources by name alone</strong>, but by:</p>
<pre><code class="language-plaintext">provider + resource_type + name
</code></pre>
<p>This combination must always be unique.</p>
<h3>🌐 2. What is a Provider in Terraform?</h3>
<p>A <strong>provider</strong> is a plugin that allows Terraform to interact with external APIs.</p>
<p>👉 In simple words:</p>
<blockquote>
<p>Provider = Bridge between Terraform and Cloud/Service</p>
</blockquote>
<h3>🔧 Why Providers are Needed?</h3>
<p>Without providers:</p>
<ul>
<li><p>Terraform cannot talk to AWS, GCP, or any service</p>
</li>
<li><p>No infrastructure can be created</p>
</li>
</ul>
<h3>📌 Popular Providers:</h3>
<ul>
<li><p>AWS (Amazon Web Services)</p>
</li>
<li><p>Google Cloud Platform (GCP)</p>
</li>
<li><p>Azure</p>
</li>
<li><p>Local (for files, local operations)</p>
</li>
</ul>
<h3>⚡ Real-Life Analogy:</h3>
<p>Think of Terraform as a <strong>remote control</strong><br />and providers as the <strong>signal system</strong> that connects it to devices.</p>
<p>Without signals → remote is useless ❌</p>
<h3><mark class="bg-yellow-200 dark:bg-yellow-500/30">⚙️ 3. Ways to Use Providers in Terraform</mark></h3>
<p>Terraform gives flexibility in how you define providers.</p>
<h3>🔹 Method 1: Implicit Provider (Automatic Way) ✅</h3>
<p>👉 The easiest and most beginner-friendly method.</p>
<p>You don’t explicitly define the provider — Terraform automatically detects it.</p>
<p>📌 Example:</p>
<pre><code class="language-shell">
resource "aws_instance" "my_vm" {
  ami           = "ami-0ec10929233384c7f"   # Example Ubuntu AMI (Mumbai)
  instance_type = "t2.micro"

  tags = {
    Name = "Terraform-VM"
  }
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a4f8dd2a-95cb-47ae-9c63-eea84a90e482.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d8fbddde-394a-4009-8e2d-efe6f0539043.png" alt="" style="display:block;margin:0 auto" />

<h3>🔍 What Happens Behind the Scenes?</h3>
<ol>
<li><p>Terraform sees <code>aws_instance</code></p>
</li>
<li><p>It understands provider = <strong>aws</strong></p>
</li>
<li><p>During initialization, it automatically downloads the provider</p>
</li>
</ol>
<h3>▶️ Steps:</h3>
<pre><code class="language-plaintext">terraform init
</code></pre>
<p>✔ Provider gets installed automatically  </p>
<p>✔ No manual configuration needed</p>
<h3>👍 When to Use:</h3>
<ul>
<li><p>Learning phase</p>
</li>
<li><p>Small projects</p>
</li>
<li><p>Quick testing</p>
</li>
</ul>
<h3>🔹 Method 2: Explicit Provider (Declarative Way) ✅</h3>
<p>👉 This is the <strong>recommended approach for <mark class="bg-yellow-200 dark:bg-yellow-500/30"> real-world projects</mark></strong><mark class="bg-yellow-200 dark:bg-yellow-500/30">.</mark></p>
<p>You explicitly define:</p>
<ul>
<li><p>Provider source</p>
</li>
<li><p>Version</p>
</li>
</ul>
<p>📌 Step 1: Define Providers</p>
<pre><code class="language-shell">terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&gt; 6.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
}
</code></pre>
<h3>📌 Step 2: Initialize</h3>
<pre><code class="language-plaintext">terraform init
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6baa905b-c832-4c08-82df-9ddb4ce18523.png" alt="" style="display:block;margin:0 auto" />

<h3>🔍 What Happens:</h3>
<ul>
<li><p>Terraform downloads exact versions</p>
</li>
<li><p>Ensures consistency across systems</p>
</li>
<li><p>Prevents unexpected breaking changes</p>
</li>
</ul>
<h3>👍 When to Use:</h3>
<ul>
<li><p>Production environments</p>
</li>
<li><p>Team projects</p>
</li>
<li><p>Version-controlled infrastructure</p>
</li>
</ul>
<h3>⚡ 4. Implicit vs Explicit (Quick Understanding)</h3>
<h3>Implicit:</h3>
<ul>
<li><p>Automatic</p>
</li>
<li><p>Less control</p>
</li>
<li><p>Beginner-friendly</p>
</li>
</ul>
<h3>Explicit:</h3>
<ul>
<li><p>Manual definition</p>
</li>
<li><p>Full control</p>
</li>
<li><p>Production-ready</p>
</li>
</ul>
<h3>🚀 5. Pro Tips (Important for DevOps)</h3>
<p>✔ Always use <strong>explicit providers in real projects</strong><br />✔ Lock provider versions to avoid errors<br />✔ Run <code>terraform init</code> after any provider change<br />✔ Keep provider configuration in a separate file (best practice)</p>
<h3>📌 Final Summary</h3>
<ul>
<li><p>Terraform uses <strong>providers</strong> to connect with cloud/services</p>
</li>
<li><p>Resource naming follows:</p>
<pre><code class="language-plaintext">&lt;provider&gt;_&lt;resource_type&gt;
</code></pre>
</li>
<li><p>Providers can be:</p>
<ul>
<li><p>Automatically detected (Implicit)</p>
</li>
<li><p>Manually defined (Explicit)</p>
</li>
</ul>
</li>
<li><p><code>terraform init</code> is required to install providers</p>
</li>
</ul>
<h3>🔥 Conclusion</h3>
<p>Understanding providers is a <strong>game-changer in Terraform</strong>.</p>
<p>Once you master this concept, you unlock the ability to:</p>
<ul>
<li><p>Work with multiple cloud platforms</p>
</li>
<li><p>Write scalable infrastructure code</p>
</li>
<li><p>Build real-world DevOps projects</p>
</li>
</ul>
<h2><strong>👨‍💻 About the Author</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 4]]></title><description><![CDATA[Terraform Workflow: init, validate, plan, apply & destroy
🧠 Before Starting (AWS Setup)
Before using Terraform with AWS, we first need to configure AWS access on our local machine.
👉 Steps:

Install]]></description><link>https://apurv-gujjar.me/terraform-series-day-4</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-4</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[vscode extensions]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Fri, 10 Apr 2026 03:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/5f66a303-da04-464c-b45d-df7898ba9e70.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Terraform Workflow: init, validate, plan, apply &amp; destroy</h3>
<h3><mark class="bg-yellow-200 dark:bg-yellow-500/30">🧠 Before Starting (AWS Setup)</mark></h3>
<p>Before using Terraform with AWS, we first need to configure AWS access on our local machine.</p>
<p>👉 Steps:</p>
<ul>
<li>Install <strong>AWS CLI</strong></li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/b7913dd3-3f8e-4c4f-ab1e-5c88ee2896ce.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>Configure AWS using:</li>
</ul>
<pre><code class="language-plaintext">aws configure
</code></pre>
<p>👉 It will ask for:</p>
<ul>
<li><p>AWS Access Key</p>
</li>
<li><p>Secret Key</p>
</li>
<li><p>Region</p>
</li>
<li><p>Output format</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/227acca6-c6fd-41e3-81d4-68cfbbfa7d19.png" alt="" style="display:block;margin:0 auto" />

<p>✅ After this setup, Terraform can interact with your AWS account.</p>
<h3>🎯 Objective</h3>
<ul>
<li><p>Understand Terraform workflow</p>
</li>
<li><p>Learn core commands</p>
</li>
<li><p>Perform hands-on execution</p>
</li>
</ul>
<h3>🧱 Step 0: Create Terraform Configuration File</h3>
<p>👉 Create a file:</p>
<pre><code class="language-plaintext">main.tf
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/833d3314-bbbf-471d-a374-3e3e54180ccb.png" alt="" style="display:block;margin:0 auto" />

<p>👉 This file contains your Terraform infrastructure code</p>
<h3>⚙️ Step 1: Initialize Terraform</h3>
<p>🔹 Command:</p>
<pre><code class="language-plaintext">terraform init
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6c1e4c93-6752-4a11-8486-550ed16328d9.png" alt="" style="display:block;margin:0 auto" />

<p>🔹 Purpose:</p>
<ul>
<li><p>Initializes working directory</p>
</li>
<li><p>Downloads required providers</p>
</li>
<li><p>Prepares environment</p>
</li>
</ul>
<h3>✅ Step 2: Validate Configuration</h3>
<p>🔹 Command:</p>
<pre><code class="language-plaintext">terraform validate
</code></pre>
<p>🔹 Purpose:</p>
<ul>
<li><p>Checks syntax of <code>.tf</code> files</p>
</li>
<li><p>Ensures configuration is valid</p>
</li>
</ul>
<p>👉 “Check if your code is correct”</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ac81bc20-bf48-4de3-a6ba-48d0ab43242d.png" alt="" style="display:block;margin:0 auto" />

<h3>📊 Step 3: Review Execution Plan</h3>
<p>🔹 Command:</p>
<pre><code class="language-plaintext">terraform plan
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/25c9b0de-4dad-46d9-b7bb-6a9eeac196ad.png" alt="" style="display:block;margin:0 auto" />

<p>🔹 Purpose:</p>
<ul>
<li><p>Shows what Terraform will do</p>
</li>
<li><p>Lists resources to create/change/destroy</p>
</li>
<li><p>Works as a dry run</p>
</li>
</ul>
<p>👉 “Preview before execution”</p>
<h3>🚀 Step 4: Apply Configuration</h3>
<p>🔹 Command:</p>
<pre><code class="language-plaintext">terraform apply
</code></pre>
<p>🔹 Purpose:</p>
<ul>
<li><p>Executes the plan</p>
</li>
<li><p>Creates real infrastructure</p>
</li>
</ul>
<p>👉 Type <code>yes</code> to confirm</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/522bdc22-eeb6-4cb8-ad73-8a315cc9e218.png" alt="" style="display:block;margin:0 auto" />

<h3>🧨 Step 5: Destroy Infrastructure</h3>
<p>🔹 Command:</p>
<pre><code class="language-plaintext">terraform destroy
</code></pre>
<p>🔹 Purpose:</p>
<ul>
<li><p>Deletes all resources</p>
</li>
<li><p>Avoids unnecessary cloud cost</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/89dd273c-f629-4eb3-936e-de1527a54758.png" alt="" style="display:block;margin:0 auto" />

<h3>⚡ Auto-Approve Option</h3>
<pre><code class="language-plaintext">terraform apply -auto-approve
terraform destroy -auto-approve
</code></pre>
<p>👉 Skips confirmation</p>
<p>👉 Useful in automation (CI/CD)</p>
<h2><strong>👨‍💻 About the Author</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 3]]></title><description><![CDATA[Terraform Blocks, Labels, and Arguments
In Day 2, we installed Terraform.Now, before writing real infrastructure code, we must understand how Terraform actually reads and executes configurations.
👉 E]]></description><link>https://apurv-gujjar.me/terraform-series-day-3</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-3</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[k8s]]></category><category><![CDATA[vscode extensions]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Fri, 10 Apr 2026 03:20:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/c9aa8dc9-d9dc-42da-82d3-d4d335b889ec.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Terraform Blocks, Labels, and Arguments</h3>
<p>In Day 2, we installed Terraform.<br />Now, before writing real infrastructure code, we must understand <strong>how Terraform actually reads and executes configurations</strong>.</p>
<p>👉 Every Terraform file is built using 3 core concepts:</p>
<ul>
<li><p>Blocks</p>
</li>
<li><p>Labels</p>
</li>
<li><p>Arguments</p>
</li>
</ul>
<h3>🔹 1. What is a Block?</h3>
<p>👉 A block is the <strong>main building unit</strong> in Terraform used to define infrastructure or configuration.</p>
<p>📌 Example:</p>
<pre><code class="language-shell">resource "aws_instance" "my_vm" {
}
</code></pre>
<p>👉 Meaning:</p>
<ul>
<li>Block tells Terraform <strong>what you want to create</strong></li>
</ul>
<p>📌 Common blocks:</p>
<ul>
<li><p><code>resource</code></p>
</li>
<li><p><code>provider</code></p>
</li>
<li><p><code>variable</code></p>
</li>
<li><p><code>output</code></p>
</li>
</ul>
<h3>🔹 2. What are Labels?</h3>
<p>👉 Labels are <strong>identifiers of a block</strong> that define resource type and name.</p>
<p>📌 Example:</p>
<pre><code class="language-shell">resource "aws_instance" "my_vm" {
}
</code></pre>
<p>👉 Meaning:</p>
<ul>
<li><p><code>aws_instance</code> → resource type</p>
</li>
<li><p><code>my_vm</code> → resource name</p>
</li>
</ul>
<p>👉 Used to uniquely identify resources</p>
<h3>🔹 3. What are Arguments?</h3>
<p>👉 Arguments are <strong>key-value pairs inside a block</strong> used to configure the resource.</p>
<p>📌 Example:</p>
<pre><code class="language-shell">instance_type = "t2.micro"
</code></pre>
<p>👉 Meaning:</p>
<ul>
<li><p>Defines how the resource should be created</p>
</li>
<li><p>Controls behavior and properties</p>
</li>
</ul>
<p><mark class="bg-yellow-200 dark:bg-yellow-500/30">🔗 Combined Example</mark></p>
<pre><code class="language-shell">resource "aws_instance" "my_vm" {
  instance_type = "t2.micro"
}
</code></pre>
<p>👉 Breakdown:</p>
<ul>
<li><p>Block → <code>resource</code></p>
</li>
<li><p>Labels → <code>aws_instance</code>, <code>my_vm</code></p>
</li>
<li><p>Argument → <code>instance_type</code></p>
</li>
</ul>
<h2><strong>👨‍💻 About the Author</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 2]]></title><description><![CDATA[Terraform Setup on AWS EC2 & Local (Ubuntu , window )
In Day 1, we understood the fundamentals of Terraform and Infrastructure as Code (IaC).Now, in Day 2, we will set up Terraform in real environment]]></description><link>https://apurv-gujjar.me/terraform-series-day-2</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-2</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[Devops]]></category><category><![CDATA[ec2]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Fri, 10 Apr 2026 03:10:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/de599b1b-0056-4109-a6a1-fc82a585558c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Terraform Setup on AWS EC2 &amp; Local (Ubuntu , window )</h3>
<p>In Day 1, we understood the fundamentals of Terraform and Infrastructure as Code (IaC).<br />Now, in Day 2, we will set up Terraform in real environments.</p>
<p>This guide covers installation on:</p>
<ul>
<li><p>AWS EC2 (Ubuntu)</p>
</li>
<li><p>Local Ubuntu Machine</p>
</li>
<li><p>Windows (using Chocolatey)</p>
</li>
</ul>
<h3>🎯 Objective</h3>
<ul>
<li><p>Install Terraform in different environments</p>
</li>
<li><p>Follow secure installation practices</p>
</li>
<li><p>Verify installation properly</p>
</li>
</ul>
<h3><mark class="bg-yellow-200 dark:bg-yellow-500/30">☁️ Part 1: Setup on AWS EC2 (Ubuntu)</mark></h3>
<h3>🧱 Step 1: Create EC2 Instance</h3>
<ul>
<li><p>Go to AWS EC2 Dashboard</p>
</li>
<li><p>Click <strong>Launch Instance</strong></p>
</li>
<li><p>Select:</p>
<ul>
<li><p>OS → Ubuntu</p>
</li>
<li><p>Instance Type → t2.micro (Free Tier)</p>
</li>
</ul>
</li>
<li><p>Create key pair</p>
</li>
<li><p>Launch instance</p>
</li>
</ul>
<h3>🔐 Step 2: Connect via SSH</h3>
<pre><code class="language-plaintext">ssh -i your-key.pem ubuntu@your-ec2-public-ip
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/6fc32909-6fcd-4f15-9950-c0047ddce544.png" alt="" style="display:block;margin:0 auto" />

<h3>📦 Step 3: Update System</h3>
<pre><code class="language-plaintext">sudo apt-get update &amp;&amp; sudo apt-get install -y gnupg software-properties-common
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/53f9989b-0108-4539-948d-f8b6a0584ead.png" alt="" style="display:block;margin:0 auto" />

<h3>🔑 Step 4: Add HashiCorp GPG Key</h3>
<pre><code class="language-plaintext">wget -O- https://apt.releases.hashicorp.com/gpg | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg &gt; /dev/null
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/74851202-a799-4aa3-a932-420e96edc12d.png" alt="" style="display:block;margin:0 auto" />

<h3>✅ Step 5: Verify GPG Key</h3>
<pre><code class="language-plaintext">gpg --no-default-keyring \
--keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \
--fingerprint
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/367597fb-f49b-46a7-8a2e-f95e40bc41e3.png" alt="" style="display:block;margin:0 auto" />

<p>👉 Ensures authenticity and security</p>
<h3>📁 Step 6: Add Repository</h3>
<pre><code class="language-plaintext">echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/hashicorp.list
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/9fed7f68-a778-4a1a-9a9b-d4942afdffa7.png" alt="" style="display:block;margin:0 auto" />

<h3>🔄 Step 7: Update Packages</h3>
<pre><code class="language-plaintext">sudo apt-get update
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/dd524921-cce0-4198-b4a6-13e9c7aa6ffd.png" alt="" style="display:block;margin:0 auto" />

<h3>⚙️ Step 8: Install Terraform</h3>
<pre><code class="language-plaintext">sudo apt-get install terraform
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/d8dedd16-9507-4a19-9486-b6029474a30c.png" alt="" style="display:block;margin:0 auto" />

<h3>🔍 Step 9: Verify Installation</h3>
<pre><code class="language-plaintext">terraform --version
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/fa254ee3-fb6a-40a0-a8d8-4d78f6416512.png" alt="" style="display:block;margin:0 auto" />

<h3>💻 Part 2: Local Installation (Ubuntu)</h3>
<p>👉 Follow the <strong>same steps as EC2</strong></p>
<p>No changes required — works exactly the same.</p>
<h3>🪟 Part 3: Terraform Installation on Windows</h3>
<h3>📦 Step 1: Install using Chocolatey</h3>
<pre><code class="language-plaintext">choco install terraform
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/64341917-39e1-4b4d-b2c2-76e83a44fb1f.png" alt="" style="display:block;margin:0 auto" />

<p>👉 Make sure <strong>Chocolatey is installed</strong> on your system</p>
<h3>🔍 Step 2: Verify Installation</h3>
<p>Open a new terminal (CMD/PowerShell):</p>
<pre><code class="language-plaintext">terraform -help
</code></pre>
<p>Expected output:</p>
<pre><code class="language-plaintext">Usage: terraform [global options] &lt;subcommand&gt; [args]
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a5bbdf15-e299-49ff-8b38-aa625b9985fd.png" alt="" style="display:block;margin:0 auto" />

<p>👉 Shows all available Terraform commands</p>
<h3>⚡ Enable Autocomplete (Optional but Recommended)</h3>
<h3>🐧 Bash</h3>
<pre><code class="language-plaintext">touch ~/.bashrc
terraform -install-autocomplete
</code></pre>
<h3>🐚 Zsh</h3>
<pre><code class="language-plaintext">touch ~/.zshrc
terraform -install-autocomplete
</code></pre>
<p>👉 Restart terminal after this step</p>
<img src="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/70cab01c-dd28-4ad3-95e7-ae402a5a215a.png" alt="" style="display:block;margin:0 auto" />

<h3>📘 Alternative Installation Method</h3>
<p>You can also install Terraform using the official HashiCorp documentation depending on your OS and requirements.</p>
<p><a href="https://developer.hashicorp.com/terraform">Terraform official Documentation</a></p>
<h2><strong>👨‍💻 About the Author</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p><mark class="bg-yellow-200 dark:bg-yellow-500/30">“This Kubernetes series focuses on building a strong foundation by understanding real Kubernetes concepts step by step.”</mark></p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[📘  Terraform Series – Day 1]]></title><description><![CDATA[Introduction to Terraform & Infrastructure as Code (IaC)
In modern DevOps practices, managing infrastructure manually is no longer scalable or efficient. Organizations are rapidly shifting towards aut]]></description><link>https://apurv-gujjar.me/terraform-series-day-1</link><guid isPermaLink="true">https://apurv-gujjar.me/terraform-series-day-1</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[GCP]]></category><category><![CDATA[vscode extensions]]></category><category><![CDATA[ec2]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Fri, 10 Apr 2026 03:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/f984cc72-6bbe-413b-8cba-76064fda703c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Introduction to Terraform &amp; Infrastructure as Code (IaC)</h3>
<p>In modern DevOps practices, managing infrastructure manually is no longer scalable or efficient. Organizations are rapidly shifting towards <strong>automation and Infrastructure as Code (IaC)</strong> to ensure consistency, speed, and reliability.</p>
<p>This is where <strong>Terraform</strong> plays a crucial role.</p>
<h3>📌 What is Terraform?</h3>
<p>Terraform is an <strong>Infrastructure as Code (IaC)</strong> tool developed by HashiCorp that enables you to define, provision, and manage infrastructure using code.</p>
<ul>
<li><p>Uses <strong>HCL (HashiCorp Configuration Language)</strong></p>
</li>
<li><p>Follows a <strong>declarative approach</strong></p>
</li>
<li><p>Automates infrastructure lifecycle</p>
</li>
</ul>
<p>👉 Instead of manually creating resources, you define them in code and Terraform handles the execution.</p>
<h3>🏢 About HashiCorp</h3>
<p>HashiCorp is a technology company focused on building tools for:</p>
<ul>
<li><p>Infrastructure automation</p>
</li>
<li><p>Security management</p>
</li>
<li><p>Application deployment</p>
</li>
</ul>
<p>👉 Founded in <strong>2014</strong><br />👉 By <strong>Mitchell Hashimoto</strong> and <strong>Armon Dadgar</strong></p>
<p>Some popular tools by HashiCorp:</p>
<ul>
<li><p>Terraform</p>
</li>
<li><p>Vault</p>
</li>
<li><p>Consul</p>
</li>
<li><p>Nomad</p>
</li>
</ul>
<h3>⚡ Why Terraform Matters in DevOps</h3>
<p>In real-world environments, infrastructure needs to be:</p>
<ul>
<li><p><strong>Consistent</strong> across environments</p>
</li>
<li><p><strong>Scalable</strong> based on demand</p>
</li>
<li><p><strong>Repeatable</strong> without errors</p>
</li>
<li><p><strong>Automated</strong> to reduce manual effort</p>
</li>
</ul>
<p>Terraform enables all of this by:</p>
<ul>
<li><p>Eliminating manual provisioning</p>
</li>
<li><p>Enforcing infrastructure consistency</p>
</li>
<li><p>Supporting version control (Git-based workflows)</p>
</li>
<li><p>Enabling multi-cloud deployments</p>
</li>
</ul>
<h3>🌍 Real-World DevOps Scenario</h3>
<p>Consider a company managing multiple environments:</p>
<ul>
<li><p><strong>Development</strong></p>
</li>
<li><p><strong>Testing</strong></p>
</li>
<li><p><strong>Production</strong></p>
</li>
</ul>
<p>Each environment requires:</p>
<ul>
<li><p>Virtual Machines</p>
</li>
<li><p>Networking setup</p>
</li>
<li><p>Load balancing</p>
</li>
</ul>
<h3>❌ Without Terraform</h3>
<ul>
<li><p>Manual configuration</p>
</li>
<li><p>Time-consuming process</p>
</li>
<li><p>High probability of human errors</p>
</li>
<li><p>Difficult to maintain consistency</p>
</li>
</ul>
<h3>✅ With Terraform</h3>
<ul>
<li><p>Define infrastructure once</p>
</li>
<li><p>Reuse configurations across environments</p>
</li>
<li><p>Deploy with a single command</p>
</li>
<li><p>Modify using variables and version control</p>
</li>
</ul>
<p>👉 Result: <strong>Faster, reliable, and scalable infrastructure management</strong></p>
<h3>⚔️ Terraform vs Other Tools</h3>
<h3><mark class="bg-yellow-200 dark:bg-yellow-500/30">🔹 Terraform vs Ansible</mark></h3>
<p><strong>Terraform</strong></p>
<ul>
<li><p>Focus: Infrastructure provisioning</p>
</li>
<li><p>Creates resources such as:</p>
<ul>
<li><p>Virtual Machines</p>
</li>
<li><p>Networks</p>
</li>
<li><p>Load Balancers</p>
</li>
</ul>
</li>
</ul>
<p><strong>Ansible</strong></p>
<ul>
<li><p>Focus: Configuration management</p>
</li>
<li><p>Handles:</p>
<ul>
<li><p>Software installation</p>
</li>
<li><p>System updates</p>
</li>
<li><p>Application setup</p>
</li>
</ul>
</li>
</ul>
<p>👉 In practice:<br />Terraform → <em>Creates infrastructure</em><br />Ansible → <em>Configures infrastructure</em></p>
<h3><mark class="bg-yellow-200 dark:bg-yellow-500/30">🔹 Terraform vs AWS CloudFormation</mark></h3>
<p><strong>Terraform</strong></p>
<ul>
<li><p>Supports multiple cloud providers:</p>
<ul>
<li><p>AWS</p>
</li>
<li><p>Azure</p>
</li>
<li><p>GCP</p>
</li>
</ul>
</li>
<li><p>Enables <strong>multi-cloud strategy</strong></p>
</li>
</ul>
<p><strong>AWS CloudFormation</strong></p>
<ul>
<li>Limited to <strong>AWS ecosystem only</strong></li>
</ul>
<p>👉 Terraform provides <strong>flexibility</strong>, while CloudFormation is <strong>AWS-specific</strong></p>
<h3>🧠 Key Takeaways</h3>
<ul>
<li><p>Terraform is a core DevOps tool for <strong>Infrastructure as Code</strong></p>
</li>
<li><p>It replaces manual infrastructure setup with <strong>automated workflows</strong></p>
</li>
<li><p>Supports <strong>multi-cloud environments</strong></p>
</li>
<li><p>Ensures <strong>consistency, scalability, and efficiency</strong></p>
</li>
</ul>
<h2><strong>👨‍💻 About the Author</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="" style="display:block;margin:0 auto" />

<p>“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”</p>
<h3><strong>📬 Let's Stay Connected</strong></h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[“My DevOps Interview Experience & Questions (2025)”]]></title><description><![CDATA[DevOps is one of the fastest-growing and most in-demand skills in the IT world 🌍, especially for beginners and cloud engineers 🚀. After learning DevOps tools ⚙️ and working on practical projects 💡, I recently attended two DevOps job interviews 🎯....]]></description><link>https://apurv-gujjar.me/my-devops-interview-experience-and-questions-2025</link><guid isPermaLink="true">https://apurv-gujjar.me/my-devops-interview-experience-and-questions-2025</guid><category><![CDATA[AWS]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[cicd]]></category><category><![CDATA[Jenkins]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Gujjar Apurv]]></dc:creator><pubDate>Sun, 21 Dec 2025 14:41:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766327936838/aa82218c-219b-4817-9669-ba174a05d957.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>DevOps is one of the fastest-growing and most in-demand skills in the IT world 🌍, especially for beginners and cloud engineers 🚀. After learning DevOps tools ⚙️ and working on practical projects 💡, I recently attended two DevOps job interviews 🎯. In this blog, I’m excited to share my real interview experience 📘, including the questions asked ❓, the topics covered 📌, and the key areas interviewers focused on 👀. My goal is to help beginners understand the real interview environment 💼, build confidence 💪, and get a clear idea of what companies truly expect from DevOps candidates 🌟.</p>
<details><summary>📝 Note:</summary><div data-type="detailsContent">All the interview answers shared in this blog are based on my own experience and the responses I gave during my interviews. If you feel any answer needs correction or improvement, please update it as per your understanding. The purpose of this blog is to share real DevOps interview-learning experiences, not to claim that every answer is perfect. 😊</div></details>

<p>🟢 <strong><mark>Interview Question 1: “Tell me about yourself.”</mark></strong></p>
<p><strong>Answer I Gave :-</strong></p>
<p>“Good morning/afternoon, and <strong>thank you for giving me this opportunity</strong> to introduce myself.</p>
<p>My name is <strong>Gujjar Apurv</strong>, and I am a final-year BE student in Electronics and Communication Engineering. Over the past two years, I have been actively learning and practicing <mark>DevOps and Cloud technologies</mark> with strong hands-on experience. To validate my technical skills, I appeared for and successfully cleared the AWS <mark>Associate Developer certification exam</mark>, which has strengthened my foundation in cloud concepts and AWS services.</p>
<p>Recently, I was completed a Cloud Internship as a Cloud Intern at Corextech IT Services, where I gained practical experience with <mark>AWS services such as EC2, VPC, IAM, RDS, Route 53, AWS Lambda, S3, </mark> and many more. During this internship, I assisted in the <mark>deployment and monitoring</mark> of cloud-based systems. Based on my performance, the company assigned me an additional one-month responsibility to work on their live projects.</p>
<p>I have worked on <mark>multiple hands-on projects</mark>, although I have highlighted only two major ones in my resume.</p>
<p>The first project is the <strong>Netflix Clone Project</strong>, where I built a complete CI/CD pipeline using Jenkins, Docker, GitHub Actions, monitoring tools, and security integrations. I also implemented DevSecOps practices with live monitoring.</p>
<p>The second project is an <strong>AWS Three-Tier Secure Application</strong>, where I designed a scalable architecture using EC2, VPC, Subnets, RDS, Route Tables, ALB, and various other AWS components.</p>
<p>Along with technical work, I have also written <mark>technical blogs </mark> to explain my projects and tools, which helped me demonstrate my <mark>technical understanding and documentation skills.</mark></p>
<p>These experiences have helped me build confidence in automation, deployment, cloud monitoring, Linux server handling, and scripting skills that are essential in the DevOps industry.</p>
<p>Thank you.”</p>
<p>🟢 <strong><mark>Interview Question 2: “Why did you choose DevOps, and what is DevOps?”</mark></strong></p>
<p>“I chose DevOps because I enjoy automation, cloud technologies, and improving system efficiency. DevOps matches my problem-solving mindset and gives me the opportunity to work end-to-end building faster, scalable, and reliable environments.”</p>
<p>“DevOps is a set of practices that helps teams build and deploy software faster using automation. It reduces errors, improves delivery speed, and enhances collaboration between development and operations teams.”</p>
<p>🟢 <strong><mark>Interview Question 3: “Give one DevOps example which is related to the industry.”</mark></strong></p>
<p>“For example, when a developer pushes code to GitHub, a CI/CD pipeline automatically builds, tests, and deploys the application to the server. This removes manual steps, reduces errors, and speeds up software delivery.</p>
<p>🟢 <strong><mark>Interview Question 4: “What is your strength and weakness?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />✅ <strong>Strength:</strong><br />“My strength is that I am a quick learner and I adapt to new technologies faster.<br />⚠️ <strong>Weakness:</strong><br />“My weakness is that I am detail-oriented, and sometimes I over-polish my work.</p>
<p><strong>🟢 <mark>Interview Question 5: “What is Cloud vs Cloud Computing?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p><strong>☁️ Cloud:</strong></p>
<p>“The cloud is a platform that <mark>stores and analyzes data</mark> over the internet instead of using a local system.”</p>
<p><strong>💻 Cloud Computing:</strong></p>
<p>“Cloud computing provides the <mark>delivery of computing resources</mark> like servers, storage, databases, and networking over the internet, without managing physical hardware.”</p>
<p><strong>🟢 <mark>Interview Question 6: “Types of Cloud?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<ul>
<li><p><strong>Public Cloud:</strong> Open for all users publicly over the internet.<br />  <strong>Example:</strong> AWS, Azure, Google Cloud</p>
</li>
<li><p><strong>Private Cloud:</strong> Not publicly accessible; used by a specific organization.<br />  <strong>Example:</strong> VMware, OpenStack</p>
</li>
<li><p><strong>Hybrid Cloud:</strong> A combination of public and private cloud models.<br />  <strong>Example:</strong> AWS + VMware integration</p>
</li>
</ul>
<p><strong><mark>🟢 Interview Question 7:(common for both interview )</mark></strong></p>
<p><strong><mark>“What are Cloud Service Models, and how do they compare with AWS services?”</mark></strong>**</p>
<p><strong>Answer I Gave:</strong></p>
<p>Cloud services are divided into <strong>three main models</strong>:</p>
<p><strong>1️⃣ IaaS – Infrastructure as a Service</strong></p>
<p>Provides virtual infrastructure like servers, storage, and networking resources.</p>
<p><strong>AWS Examples:</strong></p>
<ul>
<li><p>EC2 (Compute)</p>
</li>
<li><p>EBS (Storage)</p>
</li>
<li><p>S3 (Object Storage)</p>
</li>
<li><p>VPC (Networking)</p>
</li>
<li><p>ELB (Load Balancing)</p>
</li>
</ul>
<p><strong>2️⃣ PaaS – Platform as a Service</strong></p>
<p>Provides a platform to build, run, and manage applications without managing infrastructure.</p>
<p><strong>AWS Examples:</strong></p>
<ul>
<li><p>RDS (Database Platform)</p>
</li>
<li><p>Lambda (Serverless Platform)</p>
</li>
<li><p>ECS / EKS (Container Platforms)</p>
</li>
</ul>
<p><strong>3️⃣ SaaS – Software as a Service</strong></p>
<p>Provides ready-to-use software or tools on the cloud.</p>
<p><strong>AWS Examples:</strong></p>
<ul>
<li><p>CloudWatch (Monitoring Tool)</p>
</li>
<li><p>Amazon WorkMail (Email Service)</p>
</li>
<li><p>AWS Chime (Communication Service)</p>
</li>
</ul>
<p><mark>🟢 </mark> <strong><mark>Interview Question 8: -“What protocols do you know in cloud networking?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>I mentioned the basic cloud networking protocols and explained each in one line with examples:</p>
<p><strong>1️⃣ HTTP / HTTPS</strong></p>
<p>Used for web communication between client and server.<br /><strong>Example:</strong> Accessing websites or APIs through browsers.</p>
<p><strong>2️⃣ SMTP</strong></p>
<p>Used for sending emails over the internet.<br /><strong>Example:</strong> Email delivery systems and notification services.</p>
<p><strong>3️⃣ DNS</strong></p>
<p>Used to translate domain names into IP addresses.<br /><strong>Example:</strong> Creating DNS records on Route 53.</p>
<p><strong>4️⃣ TCP / UDP</strong></p>
<p>Transport layer protocols used for sending data packets between devices.<br /><strong>Example:</strong> SSH uses TCP; streaming uses UDP.</p>
<p><strong>5️⃣ POP3 (</strong><code>Post Office Protocol version 3</code>)</p>
<p>Used to receive emails from a mail server.<br /><strong>Example:</strong> Inbox downloading in email clients.</p>
<p><strong><mark>🟢 Interview Question 9:- “How will you host a website on AWS? Explain for both static and dynamic websites.</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>I asked whether the website is static or dynamic. The interviewer said both, so I explained each case separately:</p>
<p><strong>1️⃣ Static Website Hosting on AWS</strong></p>
<p>For a static website, I would:</p>
<ul>
<li><p>Use <strong>S3</strong> to store static files like HTML, CSS, JS.</p>
</li>
<li><p>Enable <strong>Static Website Hosting</strong> in S3.</p>
</li>
<li><p>Use <strong>CloudFront</strong> CDN for caching and global delivery.</p>
</li>
<li><p>Use <strong>Route 53</strong> for DNS mapping to a domain name.</p>
</li>
</ul>
<p>👉 Result: Fast, secure, scalable static website hosting.</p>
<p><strong>2️⃣ Dynamic Website Hosting on AWS</strong></p>
<p>For a dynamic website, I would:</p>
<ul>
<li><p>Use <strong>EC2</strong> instance to run the backend application.</p>
</li>
<li><p>Use <strong>Load Balancer (ALB/ELB)</strong> to distribute traffic.</p>
</li>
<li><p>Use <strong>Auto Scaling Group</strong> to handle traffic load.</p>
</li>
<li><p>Use <strong>RDS</strong> database for storage.</p>
</li>
<li><p>Use <strong>VPC</strong> for secure networking.</p>
</li>
<li><p>Use <strong>Route 53</strong> to map the domain.</p>
</li>
</ul>
<p>👉 Result: Highly available, secure and scalable dynamic website architecture.</p>
<p><strong><mark>🟢 Interview Question 10: (IMP)</mark></strong></p>
<p><mark>“Difference Between static and dynamic hosting, why is it needed, and how does it work?”</mark></p>
<p><strong>Answer I Gave:</strong></p>
<p>I explained that DNS is used in <strong>both static and dynamic hosting</strong>, because in both cases users access the website through a domain name, and DNS maps that domain to the correct server or endpoint.</p>
<p><strong><mark>Static website hosting</mark></strong> serves fixed content directly from <strong>S3 via CloudFront</strong>, and DNS points to the CloudFront distribution.<br /><strong><mark>Dynamic website hosting</mark></strong> generates real-time content using <strong>EC2 (behind ALB) with a database like RDS</strong>, and DNS points to the ALB.</p>
<p><strong>📌 Why DNS is needed?</strong></p>
<p>DNS <mark>converts a domain name into an IP address or endpoint URL </mark> so <mark>browsers can locate the server or hosting resource.</mark></p>
<p><strong>📌 Type of DNS Records I Mentioned:</strong></p>
<h4 id="heading-1-a-record-address-record"><strong>1️⃣ A Record (Address Record)</strong></h4>
<p>Maps a domain to an IP address.</p>
<ul>
<li><p>In static hosting → rarely needed, unless pointing to CloudFront IP via LB.</p>
</li>
<li><p>In dynamic hosting → points to EC2 or Load Balancer IP.</p>
</li>
</ul>
<p><strong>Example:</strong><br /><a target="_blank" href="http://example.com"><code>example.com</code></a> <code>→ 54.xx.xx.xx (EC2 public IP / LB IP)</code></p>
<h4 id="heading-2-cname-canonical-name-record"><strong>2️⃣ CNAME (Canonical Name Record)</strong></h4>
<p>Maps one domain name to another domain name.<br />Used for endpoints instead of IP.</p>
<p><strong>Example:</strong><br /><a target="_blank" href="http://www.example.com"><code>www.example.com</code></a> <code>→</code> <a target="_blank" href="http://xyz.cloudfront.net"><code>xyz.cloudfront.net</code></a><br /><a target="_blank" href="http://app.example.com"><code>app.example.com</code></a> <code>→</code> <a target="_blank" href="http://loadbalancer.aws.com"><code>loadbalancer.aws.com</code></a></p>
<p><strong>📌 Step-by-Step DNS Workflow I Explained:</strong></p>
<p>1️⃣ User types domain name in browser<br />2️⃣ DNS checks domain record<br />3️⃣ If <strong>A Record</strong> → returns server IP<br />4️⃣ If <strong>CNAME</strong> → returns mapped domain → then endpoint resolves to IP<br />5️⃣ Browser connects to that IP<br />6️⃣ Website loads from static bucket / LB / EC2</p>
<p><strong>🟢 <mark>Interview Question 11:</mark></strong></p>
<p><mark>“If you have one EC2 instance running a website, can you host it using S3 or Route 53? If yes, how? What IP and record type will you assign?”</mark></p>
<p><strong>Answer I Gave:</strong></p>
<p>“Yes, a website running on a single EC2 instance can be hosted using <mark>Route 53. </mark> Since it is a <mark>dynamic website</mark>, I will assign an <mark>Elastic IP</mark> to the EC2 instance and create an <mark>A record in Route 53 </mark> pointing the <mark>domain to that Elastic IP</mark>. S3 is not required because EC2 is directly serving the application.”</p>
<p><strong><mark>🟢 Interview Question 12:</mark></strong></p>
<p><mark>“How do you create an EC2 instance? What are inbound/outbound rules? Can you launch multiple EC2s at once?”</mark></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ <strong>How to create EC2:</strong></p>
<p>“Select AMI → select instance type → configure storage &amp; network → add security group rules → launch → SSH connect.”</p>
<p>✔️ <strong>Inbound Rules:</strong></p>
<p>“Allow traffic coming into EC2, like HTTP (80), HTTPS (443), SSH (22).”</p>
<p>✔️ <strong>Outbound Rules:</strong></p>
<p>“Allow traffic going out from EC2, usually open to all by default.”</p>
<p>✔️ <strong>Multiple EC2 instances:</strong></p>
<p>“Yes, we can launch multiple instances together by increasing instance count during launch or using Auto Scaling.”</p>
<p><strong><mark>🟢 Interview Question 13:</mark></strong></p>
<p><mark>“What is VPC?”</mark></p>
<p><strong>Short Answer I Gave:-</strong></p>
<p>“VPC stands for Virtual Private Cloud, and it is used as a secure and isolated network in AWS.”</p>
<p><strong><mark>🟢 Interview Question 14:</mark></strong></p>
<p><mark>“How did you implement your 3-tier architecture project?”</mark></p>
<p><strong>Short Answer I Gave:</strong></p>
<p>“First, I created a custom VPC. Then I created one public and two private subnets. After that, I attached an Internet Gateway for public access and configured a NAT Gateway for private subnet outbound access. Next, I configured route tables for public and private subnets. Then I launched EC2 instances for the web tier in the public subnet and app and database tiers in private subnets. Finally, I configured security groups to allow only required communication between the tiers.”</p>
<p><strong><mark>🟢 Interview Question 15:</mark></strong></p>
<p><mark>“If your server gets millions of traffic, how will you handle it?”</mark></p>
<p><strong>Short Answer I Gave:</strong></p>
<p>“To handle high traffic, I will use a Load Balancer to distribute requests across multiple servers. If the application needs more scalability and fault tolerance, I can migrate to Kubernetes, which automatically manages scaling, load distribution, and high availability.”</p>
<p><strong><mark>🟢 Interview Question 16:</mark></strong></p>
<p><mark>“Which subnets use inbound and outbound rules, and what are inbound and outbound rules?”</mark></p>
<p><strong>Short Answer I Gave:-</strong></p>
<p><strong>Inbound Rules:</strong><br />“Allow traffic coming into the instance like HTTP (80), HTTPS (443), SSH (22).”</p>
<p><strong>Outbound Rules:</strong><br />“Allow traffic going out from the instance usually open for internet access or updates.”</p>
<p><strong>Subnet Preference:</strong><br />“Public subnets allow inbound internet traffic; private subnets allow inbound only from internal networks.”</p>
<p><strong><mark>🟢 Interview Question 17:</mark></strong></p>
<p><mark>“You have 1 VPC with 3 subnets (Subnet-1 Public, Subnet-2 Private, Subnet-3 Private). Subnet-1 has 3 EC2 instances and other subnets have 1 EC2 each. If you want EC2s inside the public subnet to communicate with each other, will you use Internet Gateway? If yes/no, why? And how will subnet communication happen?”</mark></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ Communication inside same subnet:</p>
<p>“No, Internet Gateway is not required because instances in the same subnet can communicate with each other privately using internal IPs.”</p>
<p>✔️ Communication between different subnets:</p>
<p>“To communicate across Subnet-1, Subnet-2, and Subnet-3, I will use the same VPC routing. All subnets inside a VPC are already connected by default, so instances can communicate using private IPs without Internet Gateway.”</p>
<p>✔️ Why Internet Gateway is not needed:</p>
<p>“Internet Gateway is only needed for public internet access, not for internal VPC communication.”</p>
<p>✔️ How Subnet-1 will communicate with Subnet-2 &amp; Subnet-3:</p>
<p>“Since all subnets are in the same VPC, VPC routing table already allows internal communication. So EC2s can talk to each other using private IPs. No VPC peering or Internet Gateway is required.”</p>
<p><strong><mark>🟢 Interview Question 18:</mark></strong></p>
<p><mark>“If each subnet is in a different VPC, how will you make EC2 instances communicate with each other?”</mark></p>
<p><strong>Short Answer I Gave:</strong></p>
<p>“If each subnet is in a different VPC, I will use VPC Peering or Transit Gateway, then update route tables and security groups so EC2 instances can communicate privately without using the Internet Gateway.”</p>
<p><strong><mark>🟢 Interview Question 19:</mark></strong></p>
<p><mark>“In VPC communication, do we use Internet Gateway or NAT Gateway for communication? Why not? And why do we use VPC Peering or Transit Gateway instead?”</mark></p>
<p><strong>Short Answer I Gave:</strong></p>
<ul>
<li><p><strong>We don’t use Internet Gateway or NAT Gateway for VPC-to-VPC communication</strong>, because they are used for internet access, not internal private communication.</p>
</li>
<li><p>For connecting VPCs, we use <strong>VPC Peering</strong> or <strong>Transit Gateway</strong> because they allow <strong>private, secure communication</strong> between VPC networks.</p>
</li>
</ul>
<p><strong><mark>🟢 Interview Question 20:</mark></strong></p>
<p><mark>“What is internet access in EC2, why do we assign a public subnet, is EC2 public by default, and how do you access it?”</mark></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ <strong>What is internet access in EC2?</strong></p>
<p>“Internet access means the EC2 instance can send and receive traffic from the internet using a public IP and Internet Gateway.”</p>
<p>✔️ <strong>Why do we assign a public subnet?</strong></p>
<p>“To give EC2 internet access through the Internet Gateway. Public subnet allows the instance to be reachable from the outside network.”</p>
<p>✔️ <strong>Is EC2 public by default?</strong></p>
<p>“No. EC2 becomes public only if:</p>
<ul>
<li><p>Public IP is enabled</p>
</li>
<li><p>Subnet route points to Internet Gateway</p>
</li>
<li><p>Security group allows traffic”</p>
</li>
</ul>
<p>✔️ <strong>How do we access EC2?</strong></p>
<p>“We can access EC2 using SSH with a public IP and key pair, or through EC2 Instance Connect from the AWS console.”</p>
<p><strong><mark>🟢 Interview Question 21:</mark></strong></p>
<p><mark>“</mark><strong><mark>What is a Region in AWS? Explain with example. What is an Availability Zone?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ <strong>What is Region in AWS?</strong></p>
<p>“A Region is a physical geographical location where AWS data centers are hosted.”</p>
<p><strong>Example:</strong></p>
<ul>
<li><p>Mumbai Region → <code>ap-south-1</code></p>
</li>
<li><p>North Virginia Region → <code>us-east-1</code></p>
</li>
</ul>
<p>✔️ <strong>What is Availability Zone (AZ)?</strong></p>
<p>“AZ is a group of isolated data centers inside a region that work together to provide high availability.”</p>
<p><strong>Example:</strong></p>
<ul>
<li><p>Mumbai Region has AZs like:</p>
<ul>
<li><p><code>ap-south-1a</code></p>
</li>
<li><p><code>ap-south-1b</code></p>
</li>
<li><p><code>ap-south-1c</code></p>
</li>
</ul>
</li>
</ul>
<p><strong><mark>🟢 Interview Question 22:</mark></strong></p>
<p><strong><mark>“What is an IAM Role and how do you use it?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p><strong>What is IAM Role?</strong><br />“An IAM Role gives permission to AWS services or users without needing access keys.”</p>
<p><strong>How to use it?</strong><br />“Attach the role to EC2, Lambda, or any service to allow secure resource access.”</p>
<p><strong><mark>🟢 Interview Question 23:-</mark></strong></p>
<p><strong><mark>“Which AWS service works in a serverless model</mark></strong><mark>?”</mark></p>
<p><strong>Answer I Gave:</strong></p>
<p>“AWS Lambda is a serverless compute service that runs code without managing servers. You only upload code, and Lambda handles scaling automatically.”</p>
<p><strong><mark>✅ Linux Commands for DevOps – Quick Reference Table</mark></strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Command</td><td>Use Case (Short Description)</td></tr>
</thead>
<tbody>
<tr>
<td><strong>ls</strong></td><td>Show list of files &amp; folders</td></tr>
<tr>
<td><strong>cd</strong></td><td>Change directory</td></tr>
<tr>
<td><strong>pwd</strong></td><td>Show current directory path</td></tr>
<tr>
<td><strong>cp</strong></td><td>Copy files/folders</td></tr>
<tr>
<td><strong>mv</strong></td><td>Move or rename files/folders</td></tr>
<tr>
<td><strong>rm -rf</strong></td><td>Delete files or folders</td></tr>
<tr>
<td><strong>find</strong></td><td>Search files by name</td></tr>
<tr>
<td><strong>grep</strong></td><td>Search text inside files</td></tr>
<tr>
<td><strong>chmod</strong></td><td>Change file permissions</td></tr>
<tr>
<td><strong>chown</strong></td><td>Change file ownership</td></tr>
<tr>
<td><strong>df -h</strong></td><td>Check disk storage usage</td></tr>
<tr>
<td><strong>du -sh</strong></td><td>Check folder size</td></tr>
<tr>
<td><strong>top</strong></td><td>View live CPU + memory usage</td></tr>
<tr>
<td><strong>free -h</strong></td><td>Check RAM usage</td></tr>
<tr>
<td><strong>ps -ef</strong></td><td>Check running processes</td></tr>
<tr>
<td><strong>kill -9 PID</strong></td><td>Stop/kill stuck process</td></tr>
<tr>
<td><strong>tail -f</strong></td><td>Read live logs</td></tr>
<tr>
<td><strong>ping IP/Domain</strong></td><td>Test network connectivity</td></tr>
<tr>
<td><strong>netstat -tulnp</strong></td><td>Check open ports</td></tr>
<tr>
<td><strong>ss -tulnp</strong></td><td>Check listening ports</td></tr>
<tr>
<td><strong>yum install pkg</strong></td><td>Install package (RHEL/CentOS)</td></tr>
<tr>
<td><strong>apt install pkg</strong></td><td>Install package (Ubuntu/Debian)</td></tr>
<tr>
<td><strong>scp</strong></td><td>Secure file transfer</td></tr>
<tr>
<td><strong>curl / wget</strong></td><td>Download files</td></tr>
<tr>
<td><strong>tar -cvf</strong></td><td>Compress archive</td></tr>
<tr>
<td><strong>tar -xvf</strong></td><td>Extract archive</td></tr>
<tr>
<td><strong>systemctl start/stop/restart</strong></td><td>Manage services</td></tr>
<tr>
<td><strong>ssh -i key.pem user@ip</strong></td><td>Connect to remote server</td></tr>
<tr>
<td><strong>uname -a</strong></td><td>Show kernel details</td></tr>
<tr>
<td><strong>hostnamectl</strong></td><td>Show hostname info</td></tr>
<tr>
<td><strong>ip a / ifconfig</strong></td><td>Show IP details</td></tr>
<tr>
<td><strong>history</strong></td><td>Show executed commands</td></tr>
<tr>
<td><strong>whoami</strong></td><td>Show current user</td></tr>
</tbody>
</table>
</div><p><strong><mark>🟢 Interview Question 24:</mark></strong></p>
<p><strong><mark>“What is the difference between Virtual Machines and Docker?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><mark>VM</mark></td><td><mark>Docker</mark></td></tr>
</thead>
<tbody>
<tr>
<td>Heavy</td><td>Lightweight</td></tr>
<tr>
<td>Full OS required</td><td>Shares host OS</td></tr>
<tr>
<td>Slow startup</td><td>Fast startup</td></tr>
<tr>
<td>High resources used</td><td>Low resources used</td></tr>
<tr>
<td>Strong isolation</td><td>Process-level isolation</td></tr>
</tbody>
</table>
</div><p><strong>Short Answer:</strong><br />“VMs are heavy and slow because they run full OS; Docker is fast and lightweight because it uses containers and shares the host OS.”</p>
<p><strong><mark>🟢 Interview Question 25:</mark></strong></p>
<p><strong><mark>“What is Docker and why do we use it?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“Docker is a tool used to create, run, and manage containers for applications. It helps applications run faster, improves portability, and makes deployment easy.”</p>
<p><strong><mark>🟢 Interview Question 26:</mark></strong></p>
<p><strong><mark>“What is a Docker Image and what is a Docker Container?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Docker Image</td><td>Docker Container</td></tr>
</thead>
<tbody>
<tr>
<td>Blueprint/template of application</td><td>Running instance of the image</td></tr>
<tr>
<td>Read-only</td><td>Live, executable environment</td></tr>
<tr>
<td>Stored in registry</td><td>Runs on host machine</td></tr>
</tbody>
</table>
</div><p><strong><mark>Short Answer:</mark></strong><br />“A Docker image is a blueprint, and a container is the running instance created from that image.”</p>
<p><strong><mark>🟢 Interview Question 27:</mark></strong></p>
<p><strong><mark>“If Docker is available, why do we use Kubernetes? What is the difference?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p><strong>Docker:</strong><br />“Docker is used to create and run containers.”</p>
<p><strong>Kubernetes:</strong><br />“Kubernetes is used to manage and scale containers automatically across multiple servers.”</p>
<p><strong>Short Difference:</strong><br />“Docker runs containers. Kubernetes manages many containers.”</p>
<p><strong><mark>🟢 Interview Question 28:</mark></strong></p>
<p><strong><mark>“What is a Dockerfile? Give example and build command.”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“A Dockerfile is a script that contains instructions to build a Docker image automatically.”</p>
<p><strong>Example Dockerfile:</strong></p>
<pre><code class="lang-powershell">FROM python:<span class="hljs-number">3.9</span>
<span class="hljs-built_in">COPY</span> app.py .
CMD [<span class="hljs-string">"python"</span>, <span class="hljs-string">"app.py"</span>]
</code></pre>
<p><strong>Build Command:</strong></p>
<pre><code class="lang-powershell">docker build <span class="hljs-literal">-t</span> app .
</code></pre>
<blockquote>
<p><strong><mark>app is the image name</mark></strong></p>
<h3 id="heading-one-line-logic"><strong>🟢 One Line Logic:</strong></h3>
</blockquote>
<p><strong><mark>“Dockerfile creates the image, and Docker Compose runs the image.”</mark></strong></p>
<p><strong>🟢 Interview Question 29:</strong></p>
<p><strong>“What is Docker Compose and how does it work? Give example.”</strong></p>
<p><strong>Answer I Gave:</strong><br />“Docker Compose is a tool used to run multiple containers together using a single YAML file. It helps manage multi-container applications easily.”</p>
<p><strong>📌 How it works:</strong></p>
<ul>
<li><p>We write all container details inside <code>docker-compose.yml</code></p>
</li>
<li><p>Then run all containers with one command</p>
</li>
<li><p><strong>📌 Example:</strong></p>
</li>
</ul>
<p><strong>docker-compose.yml:</strong></p>
<pre><code class="lang-powershell">version: <span class="hljs-string">'3'</span>
services:
  web:
    image: nginx
    ports:
      - <span class="hljs-string">"80:80"</span>
</code></pre>
<p><strong>📌 Command:</strong></p>
<pre><code class="lang-powershell">docker<span class="hljs-literal">-compose</span> up <span class="hljs-literal">-d</span>
</code></pre>
<p><strong><mark>🟢 Interview Question 30 : -</mark></strong></p>
<p><strong><mark>“If your system gets millions of traffic and you don’t want to manage EC2 manually, what will you use?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I will use Kubernetes because it automatically handles scaling, deployment, traffic distribution, self-healing, and node management. It creates and manages containers without manually launching EC2 instances.”</p>
<p><strong><mark>🟢 Interview Question 31:</mark></strong></p>
<p><strong><mark>“What is Kubernetes?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“Kubernetes is a container orchestration tool that automates deployment, scaling, and management of containerized applications.”</p>
<p><strong><mark>🟢 Interview Question 32:</mark></strong></p>
<p><strong><mark>“What are Pod, Deployment, and Service in Kubernetes?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ <strong>Pod:</strong></p>
<p>“Pod is the smallest unit in Kubernetes that runs one or more containers.”</p>
<p>✔️ <strong>Deployment:</strong></p>
<p>“Deployment manages multiple Pods and enables easy updates, scaling, and rollback.”</p>
<p>✔️ <strong>Service:</strong></p>
<p>“Service exposes Pods to the network so applications can communicate internally or externally.”</p>
<p><strong><mark>🟢 Interview Question 33:</mark></strong></p>
<blockquote>
<p>“First, when a developer pushes code to GitHub, it triggers the CI pipeline.<br />The pipeline pulls the code and automatically builds the application using GitHub Actions or Jenkins.<br />Next, SonarQube performs static code analysis to check code quality and security issues.<br />After that, a Docker image is built and pushed to the container registry.<br />Then, Trivy scans the Docker image to identify security vulnerabilities.<br />For monitoring, Prometheus collects metrics and Grafana provides visual dashboards.<br />Finally, the container image is deployed to the production environment.”</p>
</blockquote>
<p>✔️ <strong>Summary:</strong></p>
<p>“In my Netflix clone CI/CD project, code went from GitHub → Jenkins/GitHub Actions → SonarQube → Docker → Trivy → Monitoring → Deployment.”</p>
<p><strong><mark>🟢 Interview Question 34:</mark></strong></p>
<p><strong><mark>“If you use a public IP to access a server, how is it secure? Anyone can access it, right?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>“Public IP is safe because access depends on security group rules + SSH keys, not on IP alone.”</p>
<p><strong><mark>🟢 Interview Question 35:</mark></strong></p>
<p><strong><mark>“Give one combined real scenario where monitoring and security tools work together.”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>“In my Netflix clone deployment, I used Prometheus and Grafana to monitor container performance like CPU, RAM, latency, and traffic load. SonarQube was used for code scanning, and Docker images were scanned with Trivy for vulnerabilities. If any issue occurs, Prometheus alerts trigger notifications. This setup helped maintain application health, performance, and security continuously all in one workflow.”</p>
<p><strong><mark>🟢 Interview Question 36:</mark></strong></p>
<p><strong><mark>“What is CI/CD, and how does Jenkins help? Also, what is the difference between Jenkins and GitHub Actions?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ <strong>What is CI?</strong></p>
<p>“CI (Continuous Integration) means automatically building and testing code whenever developers push changes.”</p>
<p>✔️ <strong>What is CD?</strong></p>
<p>“CD (Continuous Deployment/Delivery) means automatically deploying applications to servers or containers after testing.”</p>
<p>✔️ <strong>How Jenkins helps?</strong></p>
<p><strong>“CI/CD automates build, test, and deployment. Jenkins is the tool to do it. GitHub Actions is a simpler, cloud-based CI/CD alternative.”</strong></p>
<p><strong><mark>🟢 Interview Question 37:</mark></strong></p>
<p><strong><mark>“What is Git and what is GitHub?”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ <strong>Git:</strong></p>
<p>“Git is a version control system used to track and manage source code changes.”</p>
<p>✔️ <strong>GitHub:</strong></p>
<p>“GitHub is a cloud platform used to store Git repositories and collaborate with others online.”</p>
<p><strong><mark>🟢 Interview Question 38:</mark></strong></p>
<p><strong><mark>“Explain the Git workflow from </mark></strong> <code>git init</code> <strong><mark>to pull request.”</mark></strong></p>
<p><strong>Answer I Gave:</strong></p>
<p>✔️ <strong>1️⃣ git init</strong></p>
<p>Start a new local repository.</p>
<p>✔️ <strong>2️⃣ git add .</strong></p>
<p>Add files to staging.</p>
<p>✔️ <strong>3️⃣ git commit -m “msg”</strong></p>
<p>Save changes in local repo.</p>
<p>✔️ <strong>4️⃣ git branch -M main</strong></p>
<p>Set main branch name.</p>
<p>✔️ <strong>5️⃣ git remote add origin &lt;URL&gt;</strong></p>
<p>Connect local repo to GitHub.</p>
<p>✔️ <strong>6️⃣ git push -u origin main</strong></p>
<p>Upload code to GitHub.</p>
<p>✔️ <strong>7️⃣ Create new branch</strong></p>
<p>Work on new feature.</p>
<p>✔️ <strong>8️⃣ git push (new branch)</strong></p>
<p>Push branch to GitHub.</p>
<p>✔️ <strong>9️⃣ Create Pull Request</strong></p>
<p>Compare branch → merge → review.</p>
<p><strong>Short path :-</strong><br /><mark>“init → add → commit → push → branch → pull request → merge.”</mark></p>
<h3 id="heading-interview-question-39"><strong><mark>Interview Question 39:</mark></strong></h3>
<p><strong><mark>“What is Shell Scripting, and why is it used in DevOps?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“Shell scripting automates Linux tasks using command sequences. In DevOps, it is used for automation, deployments, monitoring, log management, and server tasks.”</p>
<p><strong><mark>Interview Question 40:</mark></strong></p>
<p><strong><mark>“What is Shebang (#!) in shell script?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“Shebang tells Linux which interpreter should run the script, such as ‘#!/bin/bash’.”</p>
<p><strong><mark>Interview Question 41:</mark></strong></p>
<p><strong><mark>“How do you make a script executable?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“By using: chmod +x <a target="_blank" href="http://script.sh">script.sh</a>”</p>
<p><strong><mark>Interview Question 42:</mark></strong></p>
<p><strong><mark>“How do you run a shell script?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“By executing: ./<a target="_blank" href="http://script.sh">script.sh</a>”</p>
<p><strong><mark>Interview Question 43:</mark></strong></p>
<p><strong><mark>“Real scenario: If a service stops working, how will you restart it using shell script?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I will automate it using systemctl commands inside a shell script to restart the service automatically if it fails.”</p>
<p><strong><mark>Interview Question 44:</mark></strong></p>
<p><strong><mark>“How do you search for errors inside a log file using shell script?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I will use grep inside a shell script to filter error lines e.g., grep ‘ERROR’ app.log.”</p>
<p><strong><mark>Interview Question 45:</mark></strong></p>
<p><strong><mark>“How do you schedule a shell script automatically?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I will use cron jobs by running: crontab -e”</p>
<p><strong><mark>Interview Question 46:</mark></strong></p>
<p><strong><mark>“Give one real DevOps example of Shell Script.”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I used shell script to automate backup using tar, which removed manual effort.</p>
<p><strong><mark>Interview Question 47:</mark></strong></p>
<p><strong><mark>“Why is Python used in DevOps?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“Python is used for automation, cloud scripting, API integration, data parsing, monitoring, and CI/CD workflows.”</p>
<p><strong><mark>Interview Question 48:</mark></strong></p>
<p><strong><mark>“Do you know Python scripting?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“Yes, I know basic Python and can write automation scripts if needed.”</p>
<p><strong><mark>Interview Question 49:</mark></strong></p>
<p><strong><mark>“Give one real example of Python automation in DevOps.”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I used Python to collect CPU and memory usage metrics automatically and send alerts.”</p>
<p><strong><mark>Interview Question 50:</mark></strong></p>
<p><strong><mark>“What is pip?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“pip is a Python package installer used to install libraries and modules.”</p>
<p><strong><mark>Interview Question 51:</mark></strong></p>
<p><strong><mark>“How do you automate AWS services using Python?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I will use Python with boto3 library to create, manage, and automate AWS cloud operations.”</p>
<p><strong><mark>Interview Question 52:</mark></strong></p>
<p><strong><mark>“Shell scripting vs Python scripting in DevOps?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“Shell scripting is best for OS tasks, while Python is best for cloud automation, APIs, and data handling.”</p>
<p><strong><mark>Interview Question 53:</mark></strong></p>
<p><strong><mark>“How will you scan logs and extract errors using Python?”</mark></strong></p>
<p><strong>Answer I Gave:</strong><br />“I will loop through log file lines in Python and print the lines containing the keyword ‘ERROR’.”</p>
<h3 id="heading-extra-advanced-devops-interview-questions"><strong><em><mark>🟢 EXTRA ADVANCED DEVOPS INTERVIEW QUESTIONS</mark></em></strong></h3>
<p><strong>Q1: Hard link vs Soft link?</strong></p>
<p>Hard link = real file copy; Soft link = shortcut link.</p>
<p><strong>Q2: Find top 10 biggest files?</strong></p>
<p><code>du -ah / | sort -rh | head -n 10</code></p>
<p><strong>Q3: Check which port is in use?</strong></p>
<p><code>lsof -i :80</code></p>
<p><strong>Q4: Check live disk I/O?</strong></p>
<p><code>iotop</code></p>
<p><strong>Q5: Check failed login attempts?</strong></p>
<p><code>cat /var/log/secure</code></p>
<p><strong>Q6: SSH not working — how to access server?</strong></p>
<p>Use AWS Console or Session Manager.</p>
<p><strong>Q7: High server load — first check?</strong></p>
<p>Check CPU with <code>top</code>.</p>
<p><strong>Q8: Find zombie processes?</strong></p>
<p><code>ps aux | grep Z</code></p>
<p><strong>Q9: Check highest CPU usage process?</strong></p>
<p><code>top -o %CPU</code></p>
<p><strong>Q10: Trace network packets?</strong></p>
<p><code>tcpdump</code></p>
<h2 id="heading-advanced-docker-k8s"><strong><mark>🟢 ADVANCED DOCKER / K8s</mark></strong></h2>
<p><strong>Q11: What is overlay network?</strong></p>
<p>Allows containers to talk across multiple hosts.</p>
<p><strong>Q12: How Kubernetes auto-scales?</strong></p>
<p>Using Horizontal Pod Autoscaler.</p>
<p><strong>Q13: Liveness vs Readiness probe?</strong></p>
<p>Liveness = container running; Readiness = ready for traffic.</p>
<p><strong>Q14: What if Kubernetes master fails?</strong></p>
<p>Cluster control breaks — need HA setup.</p>
<p><strong>Q15: Why etcd used?</strong></p>
<p>Stores Kubernetes cluster data.</p>
<h2 id="heading-advanced-cicd"><strong><mark>🟢 ADVANCED CI/CD</mark></strong></h2>
<p><strong>Q16: Canary deployment?</strong></p>
<p>Release to small users first, then full rollout.</p>
<p><strong>Q17: Handle secrets in pipeline?</strong></p>
<p>Use Secrets Manager or Vault.</p>
<p><strong>Q18: What is an artifact?</strong></p>
<p>Build output like Docker image or JAR.</p>
<p><strong>Q19: How to rollback deployment?</strong></p>
<p>Deploy the previous version again.</p>
<p><strong>Q20: Trigger pipeline automatically?</strong></p>
<p>Using webhook.</p>
<h3 id="heading-aws-scenario"><strong><mark>🟢 AWS SCENARIO</mark></strong></h3>
<p><strong>Q21: Public IP changes after reboot fix?</strong></p>
<p>Use Elastic IP.</p>
<p><strong>Q22: How is S3 secure?</strong></p>
<p>Bucket policy + IAM + encryption.</p>
<p><strong>Q23: RDS high load fix?</strong></p>
<p>Add read replicas.</p>
<p><strong>Q24: AWS cost increasing check how?</strong></p>
<p>Use Cost Explorer.</p>
<p><strong><mark>🟢 NETWORKING</mark></strong></p>
<p><strong>Q25: Website slow first check?</strong></p>
<p>Ping to test response.</p>
<p><strong><mark>🟢 HR STYLE DEVOPS</mark></strong></p>
<p><strong>Q26: Deployment fails at night what will you do?</strong></p>
<p>Check logs, rollback safely, fix later.</p>
<p><strong>Q27: Why DevOps?</strong></p>
<p>For fast delivery and less manual work.</p>
<p><strong>Q28: Your weakness?</strong></p>
<p>Pay extra attention to details.</p>
<p><strong>Q29: Deadline is close what will you do?</strong></p>
<p>Focus on priority tasks.</p>
<p><strong><mark>🟢 ADVANCED LINUX COMMANDS</mark></strong></p>
<p><strong>Q30: htop use?</strong></p>
<p>Live process view.</p>
<p><strong>Q31: nmap use?</strong></p>
<p>Network scan.</p>
<p><strong>Q32: ncdu use?</strong></p>
<p>Disk usage view.</p>
<p><strong>Q33: strace use?</strong></p>
<p>System call trace.</p>
<p><strong>Q34: journalctl use?</strong></p>
<p>System logs.</p>
<p><strong>Q35: dig use?</strong></p>
<p>DNS check.</p>
<p><strong>Q36: rsync use?</strong></p>
<p>File sync.</p>
<p><strong>Q37: uptime use?</strong></p>
<p>System load.</p>
<p><strong>Q38: crontab -l use?</strong></p>
<p>List cron jobs.</p>
<p><strong><mark>🟢 ADVANCED DEVOPS / CLOUD CORE</mark></strong></p>
<p><strong>Q39: What is Kernel Panic?</strong></p>
<p>Fatal OS crash.</p>
<p><strong>Q40: What is inode?</strong></p>
<p>File metadata record.</p>
<p><strong>Q41: /etc/passwd vs /etc/shadow?</strong></p>
<p>passwd = users; shadow = passwords.</p>
<p><strong>Q42: What is SELinux?</strong></p>
<p>Security policy layer.</p>
<p><strong>Q43: What is race condition?</strong></p>
<p>Two processes accessing data same time → conflict.</p>
<p><strong>Q44: Ephemeral storage?</strong></p>
<p>Temporary storage for pods.</p>
<p><strong>Q45: Pod Disruption Budget?</strong></p>
<p>Stops too many pods from going offline.</p>
<p><strong>Q46: Container Registry?</strong></p>
<p>Stores container images.</p>
<p><strong>Q47: What is throttling?</strong></p>
<p>Performance reduced due to limits.</p>
<p><strong>Q48: Cache invalidation?</strong></p>
<p>Remove stale cache data.</p>
<p><strong>Q49: Sticky session LB?</strong></p>
<p>Same server for same user.</p>
<p><strong>Q50: Infrastructure drift?</strong></p>
<p>Infra state mismatch with IaC code.</p>
<p><mark>🟢 Conclusion ✨</mark></p>
<p>Preparing for a DevOps interview can feel challenging, especially for freshers but the journey becomes easier when we learn from real experiences instead of memorizing theory. In this blog, I shared every question that was asked in my two DevOps interviews, along with simple and practical answers so that anyone who is preparing can understand what companies actually expect.</p>
<p>From AWS, Linux, Networking, Docker, Kubernetes, and CI/CD pipelines to scenario-based cloud solutions these real interview learnings will save you time, build confidence, and help you prepare smarter.</p>
<p>💡 The purpose of this blog was not just to share answers,<br />but to show the <strong>process, mindset, and direction</strong> that a DevOps candidate should follow.</p>
<p>If you are a fresher like me, remember one thing:</p>
<p><strong>You do not need to know everything.</strong><br />You just need to:<br />✔️ Understand concepts<br />✔️ Build projects<br />✔️ Stay consistent<br />✔️ Keep learning<br />✔️ Believe in yourself</p>
<p>DevOps is not just about tools<br />It is about problem-solving, automation, teamwork, and continuous improvement.</p>
<p>Thank you for reading this blog.<br />I hope it helps you prepare better, feel confident, and move one step closer to your DevOps career.</p>
<p>🚀 If I can do it, you can do it too.<br />All the best, future DevOps engineers! 🔥</p>
<h2 id="heading-about-the-author"><strong>👨‍💻 About the Author</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt /></p>
<p><mark>“This series isn’t just about tools it’s about mastering real DevOps concepts and interview-ready knowledge.”</mark></p>
<h3 id="heading-lets-stay-connected">📬 Let's Stay Connected</h3>
<ul>
<li><p>📧 <strong>Email</strong>: <a target="_blank" href="mailto:gujjarapurv181@gmail.com"><strong>gujjarapurv181@gmail.com</strong></a></p>
</li>
<li><p>🐙 <strong>GitHub</strong>: <a target="_blank" href="http://github.com/ApurvGujjar07"><strong>github.com/ApurvGujjar07</strong></a></p>
</li>
<li><p>💼 <strong>LinkedIn</strong>: <a target="_blank" href="http://linkedin.com/in/apurv-gujjar"><strong>linkedin.com/in/apurv-gujjar</strong></a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>