<?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[Suyash Bhawsar]]></title><description><![CDATA[Tech enthusiast, DevOps learner. Arch Linux w/ KDE. Rust learner. Harmonium player. Sudoku solver. Passionate about music and technology.]]></description><link>https://suyashbhawsar.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 19 May 2026 03:04:39 GMT</lastBuildDate><atom:link href="https://suyashbhawsar.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Make in 2025 - The DevOps Secret Weapon You Already Have]]></title><description><![CDATA[TL;DR

Make and Makefiles remain highly relevant in 2025 for DevOps and SysAdmin automation
They offer simplicity, dependency tracking, and portability that modern alternatives still can't match
Best practices include using .PHONY, .DELETE_ON_ERROR, ...]]></description><link>https://suyashbhawsar.com/make-in-2025-the-devops-secret-weapon-you-already-have</link><guid isPermaLink="true">https://suyashbhawsar.com/make-in-2025-the-devops-secret-weapon-you-already-have</guid><category><![CDATA[Makefile]]></category><category><![CDATA[Devops]]></category><category><![CDATA[make]]></category><category><![CDATA[automation]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Suyash Bhawsar]]></dc:creator><pubDate>Fri, 02 May 2025 11:08:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759953026131/36865a17-74ce-4ac6-902a-49f101545a42.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-tldr">TL;DR</h2>
<ul>
<li><strong>Make</strong> and <strong>Makefiles</strong> remain highly relevant in 2025 for DevOps and SysAdmin automation</li>
<li>They offer simplicity, dependency tracking, and portability that modern alternatives still can't match</li>
<li>Best practices include using <code>.PHONY</code>, <code>.DELETE_ON_ERROR</code>, and automatic dependency generation</li>
<li>Practical examples show how Make excels at Docker builds, Terraform workflows, and CI/CD pipelines</li>
</ul>
<p><strong>Updated for 2025</strong>: This guide reflects current industry changes, including Terraform's 2023 license shift and updated company references.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>It's 2025, and with countless new automation tools flooding the market, you might wonder why a tool from 1976 is still in your DevOps toolkit. But Make, with its simple yet powerful Makefiles, continues to be the secret weapon of efficient teams worldwide.</p>
<p>Why? Because Make does one thing exceptionally well: it creates predictable, reproducible automation that <strong>just works</strong>. No complex dependencies, no heavy frameworks, just clean automation that runs anywhere.</p>
<p>Let's explore how this vintage tool is still making waves in modern DevOps.</p>
<h2 id="heading-what-can-make-do-for-you-a-quick-demo">What Can Make Do For You? A Quick Demo</h2>
<p>Imagine simplifying this complex workflow:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Without Make - repetitive, error-prone commands</span>
docker compose build app
docker compose run --rm app go <span class="hljs-built_in">test</span> ./...
docker compose push app
terraform init
terraform plan -out=tfplan
terraform apply tfplan
</code></pre>
<p>Into this elegant command:</p>
<pre><code class="lang-bash">make deploy
</code></pre>
<p>First, you'll need a <code>docker-compose.yml</code>:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">app:</span>
    <span class="hljs-attr">build:</span> <span class="hljs-string">.</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">myapp:latest</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">.:/app</span>
    <span class="hljs-attr">working_dir:</span> <span class="hljs-string">/app</span>
</code></pre>
<p>Then, a Makefile handles all the complexity behind the scenes:</p>
<pre><code class="lang-makefile"><span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: build test deploy terraform-deploy</span>

<span class="hljs-section">build:</span>
    docker compose build app

<span class="hljs-section">test: build</span>
    docker compose run --rm app go test ./...

<span class="hljs-section">terraform-init:</span>
    terraform init

<span class="hljs-section">terraform-plan: terraform-init</span>
    terraform plan -out=tfplan

<span class="hljs-section">terraform-apply: terraform-plan</span>
    terraform apply tfplan

<span class="hljs-section">deploy: test terraform-apply</span>
    docker compose push app
    echo <span class="hljs-string">"Deployment complete!"</span>
</code></pre>
<h2 id="heading-how-make-makes-devops-easier">How Make Makes DevOps Easier</h2>
<p>Make instantly transforms your DevOps workflow in three crucial ways:</p>
<h3 id="heading-1-dependency-tracking-that-saves-time">1. Dependency Tracking That Saves Time</h3>
<p>Make only rebuilds what needs rebuilding. When files change, Make knows exactly which targets need to be rerun - no wasted time.</p>
<pre><code class="lang-makefile"><span class="hljs-section">app: main.go utils.go config.go</span>
    go build -o app
</code></pre>
<p>Run <code>make app</code> once, change only <code>utils.go</code>, and Make will rebuild only what's necessary.</p>
<h3 id="heading-2-standardized-commands-across-projects">2. Standardized Commands Across Projects</h3>
<p>No more remembering different commands for different projects:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Same commands work across all projects</span>
make build
make <span class="hljs-built_in">test</span>
make deploy
</code></pre>
<p>This standardization reduces errors and dramatically speeds up onboarding.</p>
<h3 id="heading-3-perfect-portability">3. Perfect Portability</h3>
<p>Make runs on virtually any system without special requirements. A Makefile written today will likely still work decades from now - try saying that about most modern tools!</p>
<h2 id="heading-three-good-practices-for-better-cicd-makefiles">Three Good Practices for Better CI/CD Makefiles</h2>
<p>Want to write Makefiles that your team will thank you for? Follow these three essential practices:</p>
<h3 id="heading-1-use-phony-for-virtual-targets">1. Use <code>.PHONY</code> for Virtual Targets</h3>
<p>Mark any target that doesn't represent an actual file as <code>.PHONY</code>:</p>
<pre><code class="lang-makefile"><span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: clean build test deploy</span>

<span class="hljs-section">clean:</span>
    rm -rf build/ dist/

<span class="hljs-section">build:</span>
    go build -o app
</code></pre>
<p>This prevents confusion when a directory named "clean" or "build" exists in your project.</p>
<h3 id="heading-2-implement-deleteonerror">2. Implement <code>.DELETE_ON_ERROR</code></h3>
<p>Add this one line to ensure partially-built targets get deleted if a command fails:</p>
<pre><code class="lang-makefile"><span class="hljs-section">.DELETE_ON_ERROR:</span>

<span class="hljs-section">app:</span>
    go build -o app
    <span class="hljs-comment"># If this fails, 'app' is automatically deleted</span>
    ./app --verify
</code></pre>
<h3 id="heading-3-use-variables-for-flexibility">3. Use Variables for Flexibility</h3>
<p>Define variables at the top of your Makefile for easy configuration:</p>
<pre><code class="lang-makefile">APP_NAME := myapp
VERSION := <span class="hljs-variable">$(<span class="hljs-built_in">shell</span> git describe --tags --always)</span>
REGISTRY := example.com/registry

<span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: build push</span>

<span class="hljs-section">build:</span>
    docker build -t <span class="hljs-variable">$(REGISTRY)</span>/<span class="hljs-variable">$(APP_NAME)</span>:<span class="hljs-variable">$(VERSION)</span> .

<span class="hljs-section">push: build</span>
    docker push <span class="hljs-variable">$(REGISTRY)</span>/<span class="hljs-variable">$(APP_NAME)</span>:<span class="hljs-variable">$(VERSION)</span>
</code></pre>
<h2 id="heading-real-world-use-cases">Real-World Use Cases</h2>
<h3 id="heading-docker-build-automation">Docker Build Automation</h3>
<pre><code class="lang-makefile"><span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: docker-build docker-test docker-push</span>

<span class="hljs-section">docker-build:</span>
    docker compose build app

<span class="hljs-section">docker-test: docker-build</span>
    docker compose run --rm app npm test

<span class="hljs-section">docker-push: docker-test</span>
    docker compose push app
</code></pre>
<h3 id="heading-terraform-workflow-management">Terraform Workflow Management</h3>
<pre><code class="lang-makefile"><span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: tf-init tf-plan tf-apply</span>

<span class="hljs-section">tf-init:</span>
    terraform init

<span class="hljs-section">tf-plan: tf-init</span>
    terraform plan -out=tfplan

<span class="hljs-section">tf-apply: tf-plan</span>
    terraform apply tfplan
</code></pre>
<p><strong>Note on Terraform in 2025</strong>: While the CLI commands remain unchanged, Terraform's license shifted to Business Source License (BSL) in 2023, restricting commercial SaaS usage without a paid license. This has led many teams to adopt open-source alternatives like <a target="_blank" href="https://opentofu.org/">OpenTofu</a>, a community-driven fork that maintains full compatibility. Consider evaluating OpenTofu if open-source licensing is critical for your organization.</p>
<h3 id="heading-streamlined-cicd-pipeline">Streamlined CI/CD Pipeline</h3>
<pre><code class="lang-makefile"><span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: ci</span>

<span class="hljs-section">ci: lint test build deploy</span>

<span class="hljs-section">lint:</span>
    golangci-lint run

<span class="hljs-section">test:</span>
    go test ./...

<span class="hljs-section">build:</span>
    go build -o app

<span class="hljs-section">deploy:</span>
    ./scripts/deploy.sh
</code></pre>
<h2 id="heading-make-vs-modern-alternatives">Make vs. Modern Alternatives</h2>
<p>While tools like Just, Task, and custom shell scripts exist, Make's widespread adoption, dependency tracking, and simplicity keep it relevant. As one DevOps engineer put it in a recent discussion:</p>
<blockquote>
<p>I've tried the fancy new tools, but I keep coming back to Make. It's like a reliable old friend who never lets you down.</p>
</blockquote>
<h2 id="heading-getting-started-in-5-minutes">Getting Started in 5 Minutes</h2>
<p>Create a file named <code>Makefile</code> in your project root:</p>
<pre><code class="lang-makefile"><span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: hello</span>

<span class="hljs-section">hello:</span>
    @echo <span class="hljs-string">"Hello, Make!"</span>
    @echo <span class="hljs-string">"You've just created your first Makefile target!"</span>
</code></pre>
<p>Run it with:</p>
<pre><code class="lang-bash">make hello
</code></pre>
<p>Congratulations! You're now using the same technology that powers builds at companies like Google, Meta, and countless others.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In 2025, Make and Makefiles continue to be the unsung heroes of DevOps automation. Their simplicity, portability, and powerful dependency management make them indispensable for teams that value reliability and efficiency.</p>
<p>Whether you're building Docker images, managing Terraform workflows, or streamlining CI/CD pipelines, Make offers a battle-tested solution that just works.</p>
<p>Ready to simplify your automation? Start with a basic Makefile today, and discover why this 49-year-old tool still outperforms many of its modern alternatives.</p>
<h2 id="heading-further-resources">Further Resources</h2>
<ul>
<li><a target="_blank" href="https://www.gnu.org/software/make/manual/make.html">Official GNU Make Documentation</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[3. Deploying Applications on Your K3s Cluster - Practical Examples]]></title><description><![CDATA[Once your K3s cluster is up and running, the next step is deploying applications. Whether you're experimenting with Kubernetes for the first time or testing production-ready workloads locally, K3s makes it simple and efficient. In this blog, we’ll wa...]]></description><link>https://suyashbhawsar.com/3-deploying-applications-on-your-k3s-cluster-practical-examples</link><guid isPermaLink="true">https://suyashbhawsar.com/3-deploying-applications-on-your-k3s-cluster-practical-examples</guid><category><![CDATA[K3s application deployment]]></category><category><![CDATA[Deploy apps on Kubernetes]]></category><category><![CDATA[Helm with K3s]]></category><category><![CDATA[Kubernetes web app]]></category><category><![CDATA[k3s]]></category><category><![CDATA[Helm]]></category><category><![CDATA[kubernetes monitoring]]></category><dc:creator><![CDATA[Suyash Bhawsar]]></dc:creator><pubDate>Sat, 02 Mar 2024 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737834727867/ad1cec74-4d57-4b8e-af60-72f26a7dca58.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Once your K3s cluster is up and running, the next step is deploying applications. Whether you're experimenting with Kubernetes for the first time or testing production-ready workloads locally, K3s makes it simple and efficient. In this blog, we’ll walk through deploying a web application, adding a database service, and managing apps using Helm. By the end, you’ll have a solid understanding of deploying and monitoring applications on your K3s cluster.</p>
<hr />
<h2 id="heading-preparing-your-environment">Preparing Your Environment</h2>
<p>Before we dive into deploying applications, let’s ensure your environment is ready:</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ol>
<li><p>A functioning K3s cluster. (If you haven’t set one up yet, check out our guide on <a target="_blank" href="https://chatgpt.com/g/g-QFqqnKe65-techblogai/c/679539df-5cdc-8009-9a9b-f28271768bea#">Getting Started with K3s</a>.)</p>
</li>
<li><p><code>kubectl</code> installed and configured to communicate with your cluster.</p>
</li>
<li><p>Basic familiarity with Kubernetes concepts (pods, deployments, services).</p>
</li>
<li><p>Optional: Install <strong>Helm</strong> (we’ll cover this later).</p>
</li>
</ol>
<p>To verify your setup, run:</p>
<pre><code class="lang-bash">kubectl get nodes
</code></pre>
<p>You should see your K3s node(s) listed with a <code>STATUS</code> of <code>Ready</code>.</p>
<hr />
<h2 id="heading-example-deployments">Example Deployments</h2>
<p>Let’s start with a simple example: deploying a web application and a database service alongside it.</p>
<h3 id="heading-deploying-a-web-application">Deploying a Web Application</h3>
<p>We’ll deploy a basic NGINX-based web app using a YAML manifest.</p>
<ol>
<li><strong>Create a file named</strong> <code>web-app.yaml</code>:</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>  
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>  
<span class="hljs-attr">metadata:</span>  
  <span class="hljs-attr">name:</span> <span class="hljs-string">web-app</span>  
  <span class="hljs-attr">labels:</span>  
    <span class="hljs-attr">app:</span> <span class="hljs-string">web-app</span>  
<span class="hljs-attr">spec:</span>  
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">2</span>  
  <span class="hljs-attr">selector:</span>  
    <span class="hljs-attr">matchLabels:</span>  
      <span class="hljs-attr">app:</span> <span class="hljs-string">web-app</span>  
  <span class="hljs-attr">template:</span>  
    <span class="hljs-attr">metadata:</span>  
      <span class="hljs-attr">labels:</span>  
        <span class="hljs-attr">app:</span> <span class="hljs-string">web-app</span>  
    <span class="hljs-attr">spec:</span>  
      <span class="hljs-attr">containers:</span>  
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span>  
        <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:latest</span>  
        <span class="hljs-attr">ports:</span>  
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>  
<span class="hljs-string">---</span>  
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>  
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>  
<span class="hljs-attr">metadata:</span>  
  <span class="hljs-attr">name:</span> <span class="hljs-string">web-app-service</span>  
<span class="hljs-attr">spec:</span>  
  <span class="hljs-attr">selector:</span>  
    <span class="hljs-attr">app:</span> <span class="hljs-string">web-app</span>  
  <span class="hljs-attr">ports:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>  
    <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>  
    <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span>  
  <span class="hljs-attr">type:</span> <span class="hljs-string">LoadBalancer</span>
</code></pre>
<ol start="2">
<li><strong>Apply the manifest:</strong></li>
</ol>
<pre><code class="lang-bash">kubectl apply -f web-app.yaml
</code></pre>
<ol start="3">
<li><strong>Verify the deployment:</strong></li>
</ol>
<pre><code class="lang-bash">kubectl get pods
</code></pre>
<p>You should see two pods running for the <code>web-app</code> deployment.</p>
<ol start="4">
<li><strong>Access the app:</strong><br /> Find the external IP or port assigned to the <code>web-app-service</code> using:</li>
</ol>
<pre><code class="lang-bash">kubectl get svc web-app-service
</code></pre>
<p>Access the web app in your browser or via <code>curl</code>.</p>
<hr />
<h3 id="heading-adding-a-database-service">Adding a Database Service</h3>
<p>Now, let’s add a database service (e.g., MySQL) to work alongside the web app.</p>
<ol>
<li><strong>Create a file named</strong> <code>mysql.yaml</code>:</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>  
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolumeClaim</span>  
<span class="hljs-attr">metadata:</span>  
  <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-pvc</span>  
<span class="hljs-attr">spec:</span>  
  <span class="hljs-attr">accessModes:</span>  
    <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteOnce</span>  
  <span class="hljs-attr">resources:</span>  
    <span class="hljs-attr">requests:</span>  
      <span class="hljs-attr">storage:</span> <span class="hljs-string">1Gi</span>  
<span class="hljs-string">---</span>  
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>  
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>  
<span class="hljs-attr">metadata:</span>  
  <span class="hljs-attr">name:</span> <span class="hljs-string">mysql</span>  
  <span class="hljs-attr">labels:</span>  
    <span class="hljs-attr">app:</span> <span class="hljs-string">mysql</span>  
<span class="hljs-attr">spec:</span>  
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>  
  <span class="hljs-attr">selector:</span>  
    <span class="hljs-attr">matchLabels:</span>  
      <span class="hljs-attr">app:</span> <span class="hljs-string">mysql</span>  
  <span class="hljs-attr">template:</span>  
    <span class="hljs-attr">metadata:</span>  
      <span class="hljs-attr">labels:</span>  
        <span class="hljs-attr">app:</span> <span class="hljs-string">mysql</span>  
    <span class="hljs-attr">spec:</span>  
      <span class="hljs-attr">containers:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mysql</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">mysql:8.0</span>
        <span class="hljs-attr">env:</span>  
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_ROOT_PASSWORD</span>  
          <span class="hljs-attr">value:</span> <span class="hljs-string">rootpassword</span>  
        <span class="hljs-attr">ports:</span>  
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">3306</span>  
        <span class="hljs-attr">volumeMounts:</span>  
        <span class="hljs-bullet">-</span> <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/var/lib/mysql</span>  
          <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-storage</span>  
      <span class="hljs-attr">volumes:</span>  
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-storage</span>  
        <span class="hljs-attr">persistentVolumeClaim:</span>  
          <span class="hljs-attr">claimName:</span> <span class="hljs-string">mysql-pvc</span>  
<span class="hljs-string">---</span>  
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>  
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>  
<span class="hljs-attr">metadata:</span>  
  <span class="hljs-attr">name:</span> <span class="hljs-string">mysql</span>  
<span class="hljs-attr">spec:</span>  
  <span class="hljs-attr">ports:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">3306</span>  
  <span class="hljs-attr">selector:</span>  
    <span class="hljs-attr">app:</span> <span class="hljs-string">mysql</span>  
  <span class="hljs-attr">type:</span> <span class="hljs-string">ClusterIP</span>
</code></pre>
<ol start="2">
<li><strong>Apply the manifest:</strong></li>
</ol>
<pre><code class="lang-bash">kubectl apply -f mysql.yaml
</code></pre>
<ol start="3">
<li><strong>Verify the deployment:</strong></li>
</ol>
<pre><code class="lang-bash">kubectl get pods
</code></pre>
<p>Ensure the MySQL pod is running and its <code>STATUS</code> is <code>Running</code>.</p>
<p>Now your web app can connect to the MySQL service using the service name <code>mysql</code> and port <code>3306</code>.</p>
<hr />
<h2 id="heading-using-helm-charts">Using Helm Charts</h2>
<p>K3s is fully compatible with Helm, a powerful Kubernetes package manager. Helm simplifies deploying and managing complex applications with reusable templates.</p>
<h3 id="heading-installing-helm">Installing Helm</h3>
<ol>
<li><strong>Download Helm:</strong></li>
</ol>
<pre><code class="lang-bash">curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
</code></pre>
<ol start="2">
<li><strong>Verify installation:</strong></li>
</ol>
<pre><code class="lang-bash">helm version
</code></pre>
<h3 id="heading-deploying-applications-with-helm">Deploying Applications with Helm</h3>
<p>Let's use Helm to deploy WordPress (a web app + database combo).</p>
<p><strong>Note:</strong> As of August 2025, Bitnami Helm charts have been deprecated. We'll use community-maintained alternatives.</p>
<ol>
<li><strong>Add the Helm repo:</strong></li>
</ol>
<pre><code class="lang-bash">helm repo add presslabs https://presslabs.github.io/charts
helm repo update
</code></pre>
<ol start="2">
<li><strong>Install WordPress:</strong></li>
</ol>
<pre><code class="lang-bash">helm install my-wordpress presslabs/wordpress-operator
</code></pre>
<p>Alternatively, you can use a custom WordPress setup with the mysql:8.0 deployment we created earlier.</p>
<ol start="3">
<li><strong>Check the status:</strong></li>
</ol>
<pre><code class="lang-bash">helm status my-wordpress
</code></pre>
<ol start="4">
<li><strong>Access the application:</strong>
 Get the external IP of the WordPress service:</li>
</ol>
<pre><code class="lang-bash">kubectl get svc
</code></pre>
<p>Visit the IP in your browser to see your WordPress site in action.</p>
<hr />
<h2 id="heading-monitoring-and-managing-applications">Monitoring and Managing Applications</h2>
<p>Monitoring your applications is critical, even in a local environment. Here are a few tools and techniques for managing your K3s workloads:</p>
<h3 id="heading-using-kubectl-for-basic-monitoring">Using <code>kubectl</code> for Basic Monitoring</h3>
<ul>
<li><p>Check pod status:</p>
<pre><code class="lang-bash">  kubectl get pods
</code></pre>
</li>
<li><p>View pod logs:</p>
<pre><code class="lang-bash">  kubectl logs &lt;pod-name&gt;
</code></pre>
</li>
</ul>
<h3 id="heading-adding-metrics-with-prometheus-and-grafana">Adding Metrics with Prometheus and Grafana</h3>
<p><strong>Note:</strong> Since Bitnami charts are deprecated, we'll use community-maintained alternatives.</p>
<ol>
<li>Deploy Prometheus and Grafana using Helm:</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-comment"># Add prometheus-community repo</span>
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

<span class="hljs-comment"># Install kube-prometheus-stack (includes both Prometheus and Grafana)</span>
helm install prometheus prometheus-community/kube-prometheus-stack

<span class="hljs-comment"># Alternatively, install Grafana separately</span>
helm install grafana grafana/grafana
</code></pre>
<ol start="2">
<li>Access the Grafana dashboard and connect it to Prometheus as a data source for visualizing metrics.</li>
</ol>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>Deploying applications on K3s is not only straightforward but also versatile enough to handle a wide range of use cases. Whether you’re deploying simple web apps, integrating databases, or managing complex workloads with Helm, K3s provides the tools and simplicity to get the job done.</p>
<h3 id="heading-whats-next">What’s Next?</h3>
<ul>
<li><p>Experiment with scaling your applications and using K3s in multi-node setups.</p>
</li>
<li><p>Explore CI/CD pipelines for automating application deployments on your K3s cluster.</p>
</li>
<li><p>Dive deeper into monitoring tools like Prometheus, Grafana, and Loki for a robust observability stack.</p>
</li>
</ul>
<p>Have questions or cool deployment ideas? Let us know in the comments below!</p>
]]></content:encoded></item><item><title><![CDATA[2. Advanced K3s Configuration - Customizing Your Local Cluster]]></title><description><![CDATA[K3s makes Kubernetes more accessible, but its real strength lies in its flexibility. While the default setup is great for getting started, advanced configurations allow you to fine-tune your cluster to meet specific project needs. From disabling unne...]]></description><link>https://suyashbhawsar.com/fine-tuning-k3s-customizing-local-kubernetes-setup</link><guid isPermaLink="true">https://suyashbhawsar.com/fine-tuning-k3s-customizing-local-kubernetes-setup</guid><category><![CDATA[Advanced K3s]]></category><category><![CDATA[K3s configuration]]></category><category><![CDATA[Local Kubernetes customization]]></category><category><![CDATA[Add worker nodes K3s]]></category><category><![CDATA[Disable Traefik]]></category><category><![CDATA[Kubernetes optimization]]></category><category><![CDATA[k3s]]></category><dc:creator><![CDATA[Suyash Bhawsar]]></dc:creator><pubDate>Fri, 01 Mar 2024 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737834414484/000fb11e-a0a8-4525-9632-2f793a02a5d9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>K3s makes Kubernetes more accessible, but its real strength lies in its flexibility. While the default setup is great for getting started, advanced configurations allow you to fine-tune your cluster to meet specific project needs. From disabling unneeded components to scaling with worker nodes, K3s offers plenty of options for customization. In this guide, we’ll explore advanced configuration techniques to make the most out of your K3s setup.</p>
<hr />
<h2 id="heading-understanding-k3s-configuration-options">Understanding K3s Configuration Options</h2>
<p>K3s provides various ways to customize your cluster during installation. One key tool for this is the environment variable <code>INSTALL_K3S_EXEC</code>. This variable allows you to pass additional flags to the K3s installer, tailoring the setup process to suit your requirements.</p>
<h3 id="heading-key-configuration-flags">Key Configuration Flags</h3>
<ul>
<li><p><code>--disable=&lt;component&gt;</code>: Disable unnecessary default components (e.g., Traefik, metrics-server).</p>
</li>
<li><p><code>--data-dir=&lt;path&gt;</code>: Specify a custom directory for storing K3s data.</p>
</li>
<li><p><code>--cluster-init</code>: Set up a server node as the initial control plane in a multi-node cluster.</p>
</li>
</ul>
<p>These options help streamline the installation and optimize your cluster for specific use cases.</p>
<hr />
<h2 id="heading-disabling-unnecessary-features">Disabling Unnecessary Features</h2>
<p>By default, K3s includes some built-in components like Traefik (a lightweight ingress controller). However, if your project has specific requirements (e.g., using another ingress controller), you can disable these features during installation.</p>
<h3 id="heading-example-disabling-traefik">Example: Disabling Traefik</h3>
<p>To disable Traefik, run the following command:</p>
<pre><code class="lang-bash">curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC=<span class="hljs-string">"--disable=traefik"</span> sh -
</code></pre>
<p>This ensures Traefik is not installed as part of your K3s cluster. You can also disable multiple components by separating them with commas:</p>
<pre><code class="lang-bash">curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC=<span class="hljs-string">"--disable=traefik,metrics-server"</span> sh -
</code></pre>
<p>This flexibility allows you to replace K3s defaults with custom solutions, like NGINX for ingress or Prometheus for metrics.</p>
<hr />
<h2 id="heading-adding-worker-nodes">Adding Worker Nodes</h2>
<p>Scaling your cluster with additional worker nodes is straightforward in K3s.</p>
<h3 id="heading-step-1-retrieve-the-node-token">Step 1: Retrieve the Node Token</h3>
<p>On the control plane node, the token required to join worker nodes is stored at <code>/var/lib/rancher/k3s/server/node-token</code>. Retrieve it using the following command:</p>
<pre><code class="lang-bash">cat /var/lib/rancher/k3s/server/node-token
</code></pre>
<h3 id="heading-step-2-add-a-worker-node">Step 2: Add a Worker Node</h3>
<p>Run the following command on the worker node, replacing <code>&lt;IP&gt;</code> with the control plane node’s IP address and <code>&lt;TOKEN&gt;</code> with the retrieved node token:</p>
<pre><code class="lang-bash">curl -sfL https://get.k3s.io | K3S_URL=https://&lt;IP&gt;:6443 K3S_TOKEN=&lt;TOKEN&gt; sh -
</code></pre>
<p>Once the installation is complete, the worker node will automatically join the cluster.</p>
<h3 id="heading-step-3-verify-the-node-addition">Step 3: Verify the Node Addition</h3>
<p>On the control plane node, check the cluster’s nodes:</p>
<pre><code class="lang-bash">kubectl get nodes
</code></pre>
<p>You should see the worker node listed along with the control plane node(s).</p>
<hr />
<h2 id="heading-use-cases-for-advanced-configurations">Use Cases for Advanced Configurations</h2>
<h3 id="heading-resource-constrained-environments">Resource-Constrained Environments</h3>
<p>If you’re working in an environment with limited resources (e.g., Raspberry Pi or a VM), disabling unnecessary components can free up memory and CPU.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-bash">curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC=<span class="hljs-string">"--disable=traefik,local-storage"</span> sh -
</code></pre>
<h3 id="heading-custom-ingress-controller">Custom Ingress Controller</h3>
<p>If your project requires an ingress controller other than Traefik (e.g., NGINX or HAProxy), disable Traefik and deploy your preferred solution.</p>
<h3 id="heading-multi-node-clusters">Multi-Node Clusters</h3>
<p>For testing or distributed applications, adding worker nodes can simulate a production-like cluster on local hardware or VMs.</p>
<p><strong>Example:</strong></p>
<ul>
<li><p>Control plane:</p>
<pre><code class="lang-bash">  curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC=<span class="hljs-string">"--cluster-init"</span> sh -
</code></pre>
</li>
<li><p>Workers:</p>
<pre><code class="lang-bash">  curl -sfL https://get.k3s.io | K3S_URL=https://&lt;control-plane-ip&gt;:6443 K3S_TOKEN=&lt;token&gt; sh -
</code></pre>
</li>
</ul>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>K3s is not only lightweight and easy to set up but also highly customizable. By using advanced configuration options, you can tailor your local Kubernetes cluster to meet the unique demands of your projects, whether it’s for resource-constrained environments, custom workloads, or multi-node setups.</p>
<h3 id="heading-next-steps">Next Steps</h3>
<ul>
<li><p>Explore other configuration flags in the <a target="_blank" href="https://rancher.com/docs/k3s/latest/en/">K3s documentation</a>.</p>
</li>
<li><p>Experiment with deploying and benchmarking your applications on different configurations.</p>
</li>
<li><p>Try integrating tools like Helm or CI/CD pipelines with your customized K3s setup.</p>
</li>
</ul>
<p>Got specific use cases or challenges with K3s? Share them below, and let’s discuss how to optimize your cluster further!</p>
]]></content:encoded></item><item><title><![CDATA[1. Getting Started with K3s - A Step-by-Step Guide to Local Setup]]></title><description><![CDATA[Kubernetes (K8s) has revolutionized the way we manage containerized applications, but its complexity can be intimidating for developers. This is where K3s shines. Lightweight, easy to install, and perfect for local development or resource-constrained...]]></description><link>https://suyashbhawsar.com/getting-started-with-k3s-a-step-by-step-guide-to-local-setup</link><guid isPermaLink="true">https://suyashbhawsar.com/getting-started-with-k3s-a-step-by-step-guide-to-local-setup</guid><category><![CDATA[local k3s setup]]></category><category><![CDATA[kubectl setup]]></category><category><![CDATA[Lightweight Kubernetes]]></category><category><![CDATA[k3s]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[k8s]]></category><category><![CDATA[beginner]]></category><category><![CDATA[Kubernetes guide]]></category><dc:creator><![CDATA[Suyash Bhawsar]]></dc:creator><pubDate>Thu, 29 Feb 2024 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737833841504/0f694f30-41d9-4fc8-92d4-ac10e557c9e0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Kubernetes (K8s) has revolutionized the way we manage containerized applications, but its complexity can be intimidating for developers. This is where <strong>K3s</strong> shines. Lightweight, easy to install, and perfect for local development or resource-constrained environments, K3s is a stripped-down yet fully compliant Kubernetes distribution. In this guide, we’ll walk you through setting up a local K3s cluster from scratch.</p>
<hr />
<h2 id="heading-what-is-k3s-and-why-should-you-use-it">What is K3s and Why Should You Use It?</h2>
<p><strong>K3s</strong>, developed by Rancher, is a lightweight Kubernetes distribution designed with simplicity and efficiency in mind. It requires fewer resources, making it ideal for developers who want to experiment with Kubernetes on their laptops or edge devices like Raspberry Pi.</p>
<p><strong>Advantages of K3s:</strong></p>
<ul>
<li><p><strong>Resource-Friendly:</strong> Designed for environments with limited CPU and memory.</p>
</li>
<li><p><strong>Quick Installation:</strong> A single command gets you up and running in minutes.</p>
</li>
<li><p><strong>Local Development:</strong> Ideal for developers who need a Kubernetes cluster for testing applications without managing full-scale K8s.</p>
</li>
<li><p><strong>Easy Updates:</strong> Includes built-in automation for updates and patches.</p>
</li>
</ul>
<hr />
<h2 id="heading-step-1-installing-k3s">Step 1: Installing K3s</h2>
<h3 id="heading-prerequisites">Prerequisites:</h3>
<ul>
<li><p>A system running a modern Linux distribution (e.g., Ubuntu, CentOS, Debian).</p>
</li>
<li><p>Root or sudo access to the system.</p>
</li>
<li><p><code>curl</code> installed (you can install it using <code>sudo apt install curl</code> if it’s missing).</p>
</li>
</ul>
<h3 id="heading-installation-process">Installation Process</h3>
<p>To install K3s, open your terminal and run the following command:</p>
<pre><code class="lang-bash">curl -sfL https://get.k3s.io | sh -
</code></pre>
<p>What this does:</p>
<ul>
<li><p>Downloads the K3s binary.</p>
</li>
<li><p>Installs and configures K3s as a systemd service.</p>
</li>
<li><p>Sets up the control plane and starts the cluster.</p>
</li>
</ul>
<p>After the installation completes, K3s automatically sets up a Kubernetes cluster.</p>
<hr />
<h2 id="heading-step-2-accessing-your-cluster">Step 2: Accessing Your Cluster</h2>
<h3 id="heading-setting-up-the-kubeconfig-file">Setting Up the Kubeconfig File</h3>
<p>K3s creates a <code>kubeconfig</code> file at <code>/etc/rancher/k3s/k3s.yaml</code> by default. This file is needed to interact with the cluster using <code>kubectl</code>.</p>
<p>To make this file accessible to your current user, export the path to the <code>KUBECONFIG</code> environment variable:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> KUBECONFIG=/etc/rancher/k3s/k3s.yaml
</code></pre>
<p>For convenience, add this line to your shell configuration file (e.g., <code>~/.bashrc</code> or <code>~/.zshrc</code>) to persist the setting across sessions.</p>
<p>If you have <code>kubectl</code> already installed, you can now run commands directly on your K3s cluster.</p>
<hr />
<h2 id="heading-step-3-verifying-the-installation">Step 3: Verifying the Installation</h2>
<p>To ensure your K3s cluster is up and running, use the following commands:</p>
<ol>
<li><p><strong>Check Cluster Status:</strong></p>
<pre><code class="lang-bash"> kubectl get nodes
</code></pre>
<p> This should list your node(s) with a <code>STATUS</code> of <code>Ready</code>.</p>
</li>
<li><p><strong>Verify System Pods:</strong></p>
<pre><code class="lang-bash"> kubectl get pods -A
</code></pre>
<p> This lists all system pods in all namespaces. Ensure that essential services like <code>coredns</code> are running.</p>
</li>
</ol>
<hr />
<h2 id="heading-step-4-common-issues-and-troubleshooting">Step 4: Common Issues and Troubleshooting</h2>
<h3 id="heading-problem-kubectl-command-not-found">Problem: "kubectl: command not found"</h3>
<p><strong>Note:</strong> K3s automatically installs <code>kubectl</code> during installation, so this issue is rare. The kubeconfig at <code>/etc/rancher/k3s/k3s.yaml</code> is pre-configured for the installed kubectl.</p>
<p><strong>Solution (if needed):</strong> If you encounter this error due to path conflicts or custom setups, you can manually install <code>kubectl</code>:</p>
<pre><code class="lang-bash">curl -LO <span class="hljs-string">"https://dl.k8s.io/release/<span class="hljs-subst">$(curl -s https://dl.k8s.io/release/stable.txt)</span>/bin/linux/amd64/kubectl"</span>
chmod +x kubectl
sudo mv kubectl /usr/<span class="hljs-built_in">local</span>/bin/
</code></pre>
<h3 id="heading-problem-node-is-not-in-ready-state">Problem: Node is not in “Ready” state</h3>
<p><strong>Solution:</strong> Check the K3s service logs using:</p>
<pre><code class="lang-bash">sudo journalctl -u k3s.service -f
</code></pre>
<p>Look for errors such as network issues or missing dependencies.</p>
<h3 id="heading-problem-network-connectivity-issues">Problem: Network Connectivity Issues</h3>
<p><strong>Solution:</strong> Ensure ports like <code>6443</code> (Kubernetes API) are open and not blocked by a firewall.</p>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>Setting up a local K3s cluster is as simple as running a single command. Its lightweight design, combined with the full power of Kubernetes, makes it an excellent choice for development and testing. Once your cluster is running, you can deploy applications, experiment with Kubernetes concepts, and enhance your DevOps workflows—all on your local machine.</p>
<h3 id="heading-whats-next">What’s Next?</h3>
<ul>
<li><p>Experiment with deploying a sample app to your K3s cluster.</p>
</li>
<li><p>Dive deeper into Kubernetes concepts like deployments, services, and networking.</p>
</li>
<li><p>Explore K3s features like multi-node clustering and Helm chart support.</p>
</li>
</ul>
<p>Got stuck or have questions? Drop them in the comments below, and let’s troubleshoot together!</p>
]]></content:encoded></item><item><title><![CDATA[Building a Jenkins CICD Pipeline - Step-by-Step Guide]]></title><description><![CDATA[Continuous Integration/Continuous Deployment (CI/CD) is essential for modern software development. Jenkins, the popular open-source automation server, simplifies building, testing, and deploying applications. In this guide, you'll learn to set up a b...]]></description><link>https://suyashbhawsar.com/building-a-jenkins-cicd-pipeline-step-by-step-guide</link><guid isPermaLink="true">https://suyashbhawsar.com/building-a-jenkins-cicd-pipeline-step-by-step-guide</guid><category><![CDATA[Jenkins Groovy Script]]></category><category><![CDATA[Jenkins Pipeline Syntax]]></category><category><![CDATA[Slack Notifications in Jenkins]]></category><category><![CDATA[Jenkins Build Notifications]]></category><category><![CDATA[Jenkins]]></category><category><![CDATA[jenkins pipeline]]></category><category><![CDATA[#declarative-pipeline]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[DevOps Automation]]></category><dc:creator><![CDATA[Suyash Bhawsar]]></dc:creator><pubDate>Thu, 30 Nov 2023 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759952437875/35611520-3a67-41d8-af58-b5570900cbdf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<p>Continuous Integration/Continuous Deployment (CI/CD) is essential for modern software development. Jenkins, the popular open-source automation server, simplifies building, testing, and deploying applications. In this guide, you'll learn to set up a basic Jenkins pipeline with practical examples and clear instructions.</p>
<p><strong>Updated for 2025</strong>: This guide has been revised to reflect current best practices, including Java 17/21 requirements, modern repository key management, and updated Slack integration methods.</p>
<hr />
<h2 id="heading-step-1-installing-jenkins"><strong>Step 1: Installing Jenkins</strong></h2>
<h3 id="heading-commands">Commands:</h3>
<ol>
<li><p>Install Java (Java 17 or newer required; Java 21 recommended):</p>
<pre><code class="lang-bash"> sudo apt update
 sudo apt install fontconfig openjdk-21-jre -y
 java -version
</code></pre>
<p> <strong>Note</strong>: Jenkins versions from mid-2024 onward require Java 17 or newer. Java 21 is recommended for optimal performance and future compatibility.</p>
</li>
<li><p>Add Jenkins Repository (using modern keyring method):</p>
<pre><code class="lang-bash"> sudo wget -O /etc/apt/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
 <span class="hljs-built_in">echo</span> <span class="hljs-string">"deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/"</span> | sudo tee /etc/apt/sources.list.d/jenkins.list &gt; /dev/null
</code></pre>
<p> <strong>Note</strong>: The <code>apt-key</code> command has been deprecated for security reasons. This method uses isolated keyrings for safer repository key management.</p>
</li>
<li><p>Install Jenkins:</p>
<pre><code class="lang-bash"> sudo apt update
 sudo apt install jenkins -y
 sudo systemctl start jenkins
 sudo systemctl <span class="hljs-built_in">enable</span> jenkins
</code></pre>
</li>
</ol>
<hr />
<h2 id="heading-step-2-setting-up-jenkins"><strong>Step 2: Setting Up Jenkins</strong></h2>
<ol>
<li><p><strong>Unlock Jenkins</strong>: Locate the initial admin password:</p>
<pre><code class="lang-bash"> sudo cat /var/lib/jenkins/secrets/initialAdminPassword
</code></pre>
<p> Enter this password on the Jenkins setup page.</p>
</li>
<li><p><strong>Install Suggested Plugins</strong>: On the "Customize Jenkins" page, choose "Install suggested plugins."</p>
</li>
<li><p><strong>Create Admin User</strong>: Fill out the admin username, password, and email fields.</p>
</li>
</ol>
<hr />
<h2 id="heading-step-3-creating-your-first-jenkins-pipeline"><strong>Step 3: Creating Your First Jenkins Pipeline</strong></h2>
<ol>
<li><p>Go to the Jenkins dashboard.</p>
</li>
<li><p>Click <strong>"New Item"</strong> and select <strong>"Pipeline"</strong>.</p>
</li>
<li><p>Enter a name for your pipeline, e.g., <code>MyFirstPipeline</code>.</p>
</li>
<li><p>In the pipeline configuration, select <strong>"Pipeline script"</strong> and paste the following code:</p>
<pre><code class="lang-plaintext"> pipeline {
     agent any
     stages {
         stage('Build') {
             steps {
                 echo 'Building the application...'
                 // Simulate build step
                 sh 'echo "Build Step Simulated"'
             }
         }
         stage('Test') {
             steps {
                 echo 'Testing the application...'
                 // Simulate test step
                 sh 'echo "Test Step Simulated"'
             }
         }
         stage('Deploy') {
             steps {
                 echo 'Deploying the application...'
                 // Simulate deployment step
                 sh 'echo "Deploy Step Simulated"'
             }
         }
     }
 }
</code></pre>
</li>
<li><p>Save the pipeline configuration.</p>
</li>
<li><p>On the pipeline page, click <strong>"Build Now"</strong> to run the pipeline.</p>
</li>
</ol>
<hr />
<h2 id="heading-step-4-adding-source-control-integration"><strong>Step 4: Adding Source Control Integration</strong></h2>
<ol>
<li><p>Ensure Git Plugin is Available:</p>
<ul>
<li><p>The Git plugin is typically included in the "suggested plugins" bundle installed during initial setup. Check <strong>"Manage Jenkins" &gt; "Plugins" &gt; "Installed"</strong> to verify it's already installed.</p>
</li>
<li><p>If not present, navigate to <strong>"Manage Jenkins" &gt; "Plugins" &gt; "Available"</strong> and search for "Git Plugin," then install and restart Jenkins.</p>
</li>
</ul>
</li>
<li><p>Update the pipeline script to pull code from a GitHub repository:</p>
<pre><code class="lang-plaintext"> pipeline {
     agent any
     stages {
         stage('Checkout') {
             steps {
                 git url: '&lt;https://github.com/your-repo/sample.git&gt;', branch: 'main'
             }
         }
         stage('Build') {
             steps {
                 echo 'Building the application...'
                 sh 'make build'
             }
         }
         stage('Test') {
             steps {
                 echo 'Testing the application...'
                 sh 'make test'
             }
         }
     }
 }
</code></pre>
</li>
</ol>
<hr />
<h2 id="heading-step-5-adding-notifications"><strong>Step 5: Adding Notifications</strong></h2>
<ol>
<li><p>Install the Slack Notification Plugin:</p>
<ul>
<li>Go to <strong>"Manage Jenkins &gt; Plugins"</strong>, search for "Slack Notification," and install it.</li>
</ul>
</li>
<li><p>Configure Slack (using modern OAuth bot token):</p>
<ul>
<li><p>Create a custom Slack app at https://api.slack.com/apps with required OAuth scopes (<code>channels:read</code>, <code>chat:write</code>, etc.).</p>
</li>
<li><p>Install the app to your workspace and copy the <strong>Bot User OAuth Token</strong>.</p>
</li>
<li><p>In Jenkins, go to <strong>"Manage Jenkins" &gt; "Credentials"</strong> and add the token as a "Secret text" credential.</p>
</li>
<li><p>Navigate to <strong>"Manage Jenkins" &gt; "System" &gt; "Slack"</strong>:</p>
<ul>
<li>Select your credential from the dropdown</li>
<li>Enable <strong>"Custom slack app bot user"</strong></li>
<li>Set a default channel (e.g., <code>#builds</code>)</li>
<li>Test the connection</li>
</ul>
</li>
<li><p>Invite the bot to your desired Slack channel(s).</p>
<p><strong>Note</strong>: Legacy integration tokens are deprecated. Using a bot user OAuth token provides better security and supports modern Slack features.</p>
</li>
</ul>
</li>
<li><p>Update the pipeline script to send notifications:</p>
<pre><code class="lang-plaintext"> pipeline {
     agent any
     stages {
         stage('Build') {
             steps {
                 echo 'Building the application...'
             }
         }
     }
     post {
         success {
             slackSend(channel: '#builds', message: 'Build succeeded!')
         }
         failure {
             slackSend(channel: '#builds', message: 'Build failed.')
         }
     }
 }
</code></pre>
</li>
</ol>
<hr />
<h2 id="heading-step-6-monitoring-and-troubleshooting"><strong>Step 6: Monitoring and Troubleshooting</strong></h2>
<ol>
<li><p><strong>Monitor Builds</strong>:</p>
<ul>
<li>Check the pipeline dashboard for build status.</li>
</ul>
</li>
<li><p><strong>View Logs</strong>:</p>
<ul>
<li>Click a specific build and select <strong>"Console Output"</strong> for detailed logs.</li>
</ul>
</li>
</ol>
<hr />
<h3 id="heading-wrapping-up">Wrapping Up</h3>
<p>Congratulations! You've set up a Jenkins pipeline that integrates with GitHub, runs build and test stages, and sends notifications. With these foundations, you can expand your pipeline to deploy applications to production environments or integrate advanced tools like Docker, Kubernetes, or SonarQube.</p>
<p>Encourage readers to experiment with Jenkins plugins and refine their pipeline scripts for real-world projects. Happy automating!</p>
]]></content:encoded></item><item><title><![CDATA[Configuration Management Tools Comparison - Ansible vs Puppet vs Chef vs Salt]]></title><description><![CDATA[Choosing the Right Configuration Management Tool: Ansible vs Puppet vs Chef vs Salt
Configuration management is a cornerstone of modern DevOps practices. Tools like Ansible, Puppet, Chef, and Salt streamline infrastructure automation, improving effic...]]></description><link>https://suyashbhawsar.com/ansible-vs-puppet-choosing-the-right-tool-for-your-devops-journey</link><guid isPermaLink="true">https://suyashbhawsar.com/ansible-vs-puppet-choosing-the-right-tool-for-your-devops-journey</guid><category><![CDATA[Devops]]></category><category><![CDATA[configurationmanagement ]]></category><category><![CDATA[ansible]]></category><category><![CDATA[puppet]]></category><category><![CDATA[automation]]></category><category><![CDATA[sysadmin]]></category><category><![CDATA[#InfrastructureAsCode]]></category><category><![CDATA[#IaC]]></category><category><![CDATA[DevOps tools]]></category><dc:creator><![CDATA[Suyash Bhawsar]]></dc:creator><pubDate>Thu, 09 Feb 2023 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759951569483/4e3c5115-52ad-49f9-a193-897b5fb1349c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-choosing-the-right-configuration-management-tool-ansible-vs-puppet-vs-chef-vs-salt">Choosing the Right Configuration Management Tool: Ansible vs Puppet vs Chef vs Salt</h1>
<p>Configuration management is a cornerstone of modern DevOps practices. Tools like <strong>Ansible, Puppet, Chef, and Salt</strong> streamline infrastructure automation, improving efficiency and consistency. But with four major players in the market, how do you decide which tool is best for your needs? In this comprehensive guide, we'll explore their strengths, drawbacks, and ideal use cases to help you make an informed decision.</p>
<p><strong>Updated for 2025</strong>: This guide has been revised to reflect current terminology (Puppet Server vs. Puppet Master), updated market dynamics, and ecosystem maturity based on 2025 industry data.</p>
<hr />
<h2 id="heading-step-1-understanding-configuration-management-tools"><strong>Step 1: Understanding Configuration Management Tools</strong></h2>
<p>Configuration management tools automate infrastructure tasks such as:</p>
<ul>
<li><p>Deployment</p>
</li>
<li><p>Configuration</p>
</li>
<li><p>Maintenance of systems</p>
</li>
</ul>
<p>This reduces errors, speeds up deployment, and simplifies scaling. Ansible, Puppet, Chef, and Salt are all leaders in this space but differ in architecture, approach, and ideal use cases. Let's dive deeper into each tool.</p>
<hr />
<h2 id="heading-step-2-comparing-all-four-tools"><strong>Step 2: Comparing All Four Tools</strong></h2>
<h3 id="heading-key-differences"><strong>Key Differences</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td><strong>Ansible</strong></td><td><strong>Puppet</strong></td><td><strong>Chef</strong></td><td><strong>Salt</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Architecture</strong></td><td>Agentless; uses SSH for communication</td><td>Agent-server model with Puppet Server</td><td>Agent-server model with Chef Client and Chef Server</td><td>Master-minion model with event-driven communication via ZeroMQ</td></tr>
<tr>
<td><strong>Ease of Use</strong></td><td>Simple and beginner-friendly; YAML syntax</td><td>Complex; uses domain-specific language</td><td>Complex; uses Ruby DSL (Domain Specific Language)</td><td>Moderate; uses YAML syntax with Python extensibility</td></tr>
<tr>
<td><strong>Setup Time</strong></td><td>Minimal; quick to start</td><td>Time-consuming; requires SSL and agents</td><td>Moderate; requires agent installation and configuration</td><td>Moderate; requires minion agent installation</td></tr>
<tr>
<td><strong>Performance at Scale</strong></td><td>Slower with large numbers of nodes</td><td>Efficient in large environments</td><td>Highly scalable; pull-based model distributes load</td><td>Extremely fast and highly scalable; designed for thousands of nodes</td></tr>
<tr>
<td><strong>Use Cases</strong></td><td>Best for small to medium dynamic environments</td><td>Ideal for large, stable infrastructures</td><td>Best for large enterprises with complex infrastructure and compliance needs</td><td>Ideal for high-speed remote execution and real-time configuration management</td></tr>
<tr>
<td><strong>Ecosystem</strong></td><td>Mature and expansive with extensive community-contributed content</td><td>Established with many pre-built modules</td><td>Mature with extensive cookbook library and Chef Supermarket</td><td>Growing ecosystem with modular architecture and extensive built-in modules</td></tr>
<tr>
<td><strong>Compliance and Reporting</strong></td><td>Basic capabilities</td><td>Advanced reporting and compliance features</td><td>Advanced compliance automation and auditing capabilities</td><td>Built-in compliance and security automation features</td></tr>
<tr>
<td><strong>Community Support</strong></td><td>Large, active, and rapidly growing (31.7% market share)</td><td>Long-standing and robust community (14.6% market share)</td><td>Strong enterprise focus with robust community support</td><td>Active community with strong focus on performance and scalability</td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-step-3-exploring-ansible"><strong>Step 3: Exploring Ansible</strong></h2>
<p>Ansible is a modern configuration management tool known for its simplicity and agentless architecture. It communicates with managed nodes over SSH, making it easy to get started and maintain.</p>
<h3 id="heading-key-features"><strong>Key Features</strong></h3>
<ol>
<li><p><strong>Agentless Architecture</strong>:</p>
<ul>
<li><p>No need to install agents on servers.</p>
</li>
<li><p>Uses SSH, simplifying management.</p>
</li>
<li><p>Ideal for dynamic environments with frequent changes.</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Example: Running an Ansible Playbook</strong></p>
<pre><code class="lang-yaml">    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Apache</span>
      <span class="hljs-attr">hosts:</span> <span class="hljs-string">webservers</span>
      <span class="hljs-attr">tasks:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Apache</span> <span class="hljs-string">package</span>
          <span class="hljs-attr">apt:</span>
            <span class="hljs-attr">name:</span> <span class="hljs-string">apache2</span>
            <span class="hljs-attr">state:</span> <span class="hljs-string">present</span>
</code></pre>
<ol start="2">
<li><p><strong>Human-Readable Playbooks</strong>:</p>
<ul>
<li><p>Written in YAML.</p>
</li>
<li><p>Easy to read and modify, even for beginners.</p>
</li>
</ul>
</li>
<li><p><strong>Versatile Use Cases</strong>:</p>
<ul>
<li>Configuration management, application deployments, and orchestration.</li>
</ul>
</li>
<li><p><strong>Idempotency</strong>:</p>
<ul>
<li>Ensures tasks run safely multiple times without unintended changes.</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-step-4-exploring-chef"><strong>Step 4: Exploring Chef</strong></h2>
<p><strong>Chef</strong> is a mature configuration management tool that has been serving enterprise environments since 2009. Built with Ruby and using a powerful Domain Specific Language (DSL), Chef excels in complex enterprise scenarios requiring strict compliance and detailed configuration control.</p>
<h3 id="heading-key-features-1"><strong>Key Features</strong></h3>
<ol>
<li><p><strong>Agent-Server Architecture</strong>:</p>
<ul>
<li><p>Chef Client agents installed on managed nodes communicate with Chef Server</p>
</li>
<li><p>Pull-based model where nodes fetch configurations from the server</p>
</li>
<li><p>Distributed load across nodes for better scalability</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Example: Chef Recipe to Install Apache</strong></p>
<pre><code class="lang-ruby">    package <span class="hljs-string">'apache2'</span> <span class="hljs-keyword">do</span>
      action <span class="hljs-symbol">:install</span>
    <span class="hljs-keyword">end</span>

    service <span class="hljs-string">'apache2'</span> <span class="hljs-keyword">do</span>
      action [<span class="hljs-symbol">:enable</span>, <span class="hljs-symbol">:start</span>]
      supports <span class="hljs-symbol">restart:</span> <span class="hljs-literal">true</span>
    <span class="hljs-keyword">end</span>
</code></pre>
<ol start="2">
<li><p><strong>Cookbook and Recipe System</strong>:</p>
<ul>
<li><p>Configurations organized into cookbooks containing recipes</p>
</li>
<li><p>Reusable and version-controlled infrastructure code</p>
</li>
<li><p>Extensive Chef Supermarket for community cookbooks</p>
</li>
</ul>
</li>
<li><p><strong>Advanced Compliance and Testing</strong>:</p>
<ul>
<li><p>Built-in compliance automation with Chef InSpec</p>
</li>
<li><p>Comprehensive testing tools including Test Kitchen and ChefSpec</p>
</li>
<li><p>Detailed auditing and reporting capabilities</p>
</li>
</ul>
</li>
<li><p><strong>Enterprise-Grade Features</strong>:</p>
<ul>
<li><p>Chef Automate for centralized management and observability</p>
</li>
<li><p>Integration with major cloud platforms</p>
</li>
<li><p>Strong security and access control features</p>
</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-step-5-exploring-salt-saltstack"><strong>Step 5: Exploring Salt (SaltStack)</strong></h2>
<p><strong>Salt</strong> (also known as SaltStack) is a high-performance configuration management and remote execution platform designed for speed and scalability. Built with Python and using an event-driven architecture, Salt excels in environments requiring real-time infrastructure management.</p>
<h3 id="heading-key-features-2"><strong>Key Features</strong></h3>
<ol>
<li><p><strong>Master-Minion Architecture with Event System</strong>:</p>
<ul>
<li><p>Salt Master coordinates Salt Minions via ZeroMQ messaging</p>
</li>
<li><p>Event-driven communication enables real-time responses</p>
</li>
<li><p>Can manage thousands of nodes with minimal latency</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Example: Salt State to Install Nginx</strong></p>
<pre><code class="lang-yaml">    <span class="hljs-attr">nginx:</span>
      <span class="hljs-attr">pkg.installed:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span>
      <span class="hljs-attr">service.running:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">enable:</span> <span class="hljs-literal">True</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">require:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-attr">pkg:</span> <span class="hljs-string">nginx</span>
</code></pre>
<ol start="2">
<li><p><strong>High-Speed Remote Execution</strong>:</p>
<ul>
<li><p>Execute commands across thousands of systems simultaneously</p>
</li>
<li><p>Real-time results and immediate feedback</p>
</li>
<li><p>Built for dynamic, fast-paced environments</p>
</li>
</ul>
</li>
<li><p><strong>Flexible Configuration Management</strong>:</p>
<ul>
<li><p>YAML syntax for easy readability</p>
</li>
<li><p>Python extensibility for complex customizations</p>
</li>
<li><p>Support for both agent and agentless modes</p>
</li>
</ul>
</li>
<li><p><strong>Advanced Orchestration</strong>:</p>
<ul>
<li><p>Event-driven automation with Salt Reactor system</p>
</li>
<li><p>Complex workflow orchestration across multiple systems</p>
</li>
<li><p>Built-in security and compliance features</p>
</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-step-6-exploring-puppet"><strong>Step 6: Exploring Puppet</strong></h2>
<p>Puppet has been a staple in configuration management for nearly two decades (since 2005). It uses an agent-server model, ideal for large, stable environments requiring strict consistency.</p>
<h3 id="heading-key-features-3"><strong>Key Features</strong></h3>
<ol>
<li><p><strong>Scalability</strong>:</p>
<ul>
<li><p>Agent-server architecture efficiently manages thousands of nodes.</p>
</li>
<li><p>Puppet agents periodically sync with the Puppet Server to apply configurations.</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Example: Puppet Manifest to Install Apache</strong></p>
<pre><code class="lang-plaintext">    package { 'apache2':
      ensure =&gt; installed,
    }
</code></pre>
<ol start="2">
<li><p><strong>Advanced Reporting and Compliance</strong>:</p>
<ul>
<li><p>Provides detailed insights into system state.</p>
</li>
<li><p>Ensures compliance with regulatory standards.</p>
</li>
</ul>
</li>
<li><p><strong>Granular Control</strong>:</p>
<ul>
<li>Allows precise configuration of system states.</li>
</ul>
</li>
<li><p><strong>Mature Ecosystem</strong>:</p>
<ul>
<li>Large library of pre-built modules in Puppet Forge.</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-step-7-choosing-the-right-tool"><strong>Step 7: Choosing the Right Tool</strong></h2>
<p>Use the table below to match your requirements with the tool that fits best:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Scenario</strong></td><td><strong>Recommended Tool</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Small to medium, dynamic environments</td><td>Ansible</td></tr>
<tr>
<td>Large-scale infrastructures with stability focus</td><td>Puppet</td></tr>
<tr>
<td>Large enterprises with complex compliance needs</td><td>Chef</td></tr>
<tr>
<td>High-speed remote execution and real-time management</td><td>Salt</td></tr>
<tr>
<td>Teams with mixed expertise levels</td><td>Ansible</td></tr>
<tr>
<td>Environments with strict compliance requirements</td><td>Puppet or Chef</td></tr>
<tr>
<td>Quick setup and deployment needs</td><td>Ansible</td></tr>
<tr>
<td>Long-term management of stable environments</td><td>Puppet</td></tr>
<tr>
<td>Complex orchestration and workflow automation</td><td>Chef or Salt</td></tr>
<tr>
<td>Real-time infrastructure monitoring and response</td><td>Salt</td></tr>
<tr>
<td>Multi-cloud and hybrid environments</td><td>Chef or Salt</td></tr>
<tr>
<td>Container and cloud-native deployments</td><td>Ansible or Salt</td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>All four tools—<strong>Ansible, Puppet, Chef, and Salt</strong>—are excellent choices, but their optimal use cases differ significantly:</p>
<ul>
<li><p>Choose <strong>Ansible</strong> for simplicity, quick deployments, and dynamic setups with minimal overhead.</p>
</li>
<li><p>Choose <strong>Puppet</strong> for large-scale environments, strict compliance, and stable infrastructure management.</p>
</li>
<li><p>Choose <strong>Chef</strong> for complex enterprise environments requiring advanced compliance automation and detailed configuration control.</p>
</li>
<li><p>Choose <strong>Salt</strong> for high-performance scenarios requiring real-time infrastructure management and rapid remote execution.</p>
</li>
</ul>
<p>The choice ultimately depends on your team's expertise, infrastructure scale, performance requirements, and compliance needs. Consider starting with Ansible for simpler use cases, or evaluate Puppet and Chef for enterprise environments, while keeping Salt in mind for high-performance, real-time requirements.</p>
<p>With these insights, you can select the tool that best fits your team and project needs. Start automating today, and take your infrastructure management to the next level!</p>
<hr />
<h3 id="heading-key-takeaways"><strong>Key Takeaways</strong></h3>
<ul>
<li><p><strong>Ansible</strong>: Simple, flexible, and agentless - perfect for getting started quickly.</p>
</li>
<li><p><strong>Puppet</strong>: Mature, stable, and ideal for large enterprise environments.</p>
</li>
<li><p><strong>Chef</strong>: Powerful, compliance-focused, and excellent for complex enterprise scenarios.</p>
</li>
<li><p><strong>Salt</strong>: Fast, scalable, and designed for real-time infrastructure management.</p>
</li>
</ul>
<p>Happy automating!</p>
]]></content:encoded></item><item><title><![CDATA[Exploring the Shells]]></title><description><![CDATA[Welcome to our exploration of the varied landscape of Linux shells! These powerful interfaces are more than just a user's gateway to interacting with the operating system; they're a testament to Linux's flexibility and diversity. In this guide, we'll...]]></description><link>https://suyashbhawsar.com/exploring-the-shells</link><guid isPermaLink="true">https://suyashbhawsar.com/exploring-the-shells</guid><category><![CDATA[ksh]]></category><category><![CDATA[tcsh]]></category><category><![CDATA[ash]]></category><category><![CDATA[Linux Shells]]></category><category><![CDATA[Linux Sysadmin]]></category><category><![CDATA[shell]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Bash]]></category><category><![CDATA[zsh]]></category><category><![CDATA[fish]]></category><category><![CDATA[Dash]]></category><category><![CDATA[command line interface]]></category><category><![CDATA[cli]]></category><category><![CDATA[shell scripting]]></category><category><![CDATA[Linux operating system]]></category><dc:creator><![CDATA[Suyash Bhawsar]]></dc:creator><pubDate>Mon, 09 Jan 2023 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759947282577/21b57f8b-a79c-4357-beb6-96db65025786.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to our exploration of the varied landscape of Linux shells! These powerful interfaces are more than just a user's gateway to interacting with the operating system; they're a testament to Linux's flexibility and diversity. In this guide, we'll delve into the nuances of popular shells like Bash, Zsh, Fish, Ksh, Tcsh, Ash, and Dash, as well as modern alternatives like Nushell and Elvish, examining their unique features, strengths, and how they fit into the larger Linux ecosystem.</p>
<p><strong>Updated for 2025</strong>: This guide has been revised to reflect current shell development statuses, important distinctions between interactive and system shells, and the emergence of modern structured-data shells.</p>
<h2 id="heading-introduction-to-linux-shells">Introduction to Linux Shells</h2>
<p>Before we dive into the specifics, let's understand what a shell is. In Linux-based OS, a shell is a command-line interface (CLI) that allows users to interact with the operating system by typing commands. It's the mediator between the user and the kernel, translating commands into actions that the OS can execute.</p>
<h2 id="heading-the-bash-shell-the-default-standard">The Bash Shell: The Default Standard</h2>
<p>Bash (Bourne-Again SHell) is the most common default <strong>interactive shell</strong> in Linux distributions. Its popularity stems from its balance of functionality, ease of use, and compatibility. Bash is the go-to for many because of its:</p>
<ul>
<li><p><strong>Scripting capabilities:</strong> Bash scripts are powerful tools for automating tasks.</p>
</li>
<li><p><strong>Compatibility:</strong> It's the default interactive shell on many Unix-like systems, ensuring widespread support.</p>
</li>
<li><p><strong>Customizability:</strong> Bash can be tailored with aliases, functions, and prompts.</p>
</li>
<li><p><strong>Important Note:</strong> While Bash is typically the default login shell for users, many distributions (like Debian and Ubuntu) use <strong>Dash</strong> as the system shell (<code>/bin/sh</code>) for non-interactive scripts. This improves system boot performance. When writing portable system scripts, use POSIX-compliant syntax rather than Bash-specific features.</p>
</li>
</ul>
<h2 id="heading-zsh-the-power-users-choice">Zsh: The Power User's Choice</h2>
<p>Zsh (Z Shell) is often hailed as a power user's shell, offering:</p>
<ul>
<li><p><strong>Robustness:</strong> Combines features of other shells like Bash and Ksh.</p>
</li>
<li><p><strong>Themes and plugins:</strong> Oh My Zsh is a beloved framework for managing Zsh configurations, with alternatives like Prezto and Zim offering lighter, faster options.</p>
</li>
<li><p><strong>Advanced scripting:</strong> Offers features like floating-point arithmetic and enhanced globbing.</p>
</li>
<li><p><strong>Mainstream Adoption:</strong> Since macOS Catalina (2019), Zsh has been the default shell on macOS, making it a mainstream choice for developers across platforms.</p>
</li>
</ul>
<h2 id="heading-fish-a-friendly-interactive-shell">Fish: A Friendly, Interactive Shell</h2>
<p>Fish (Friendly Interactive SHell) is known for its user-friendliness, with features like:</p>
<ul>
<li><p><strong>Auto-suggestions:</strong> Fish suggests commands as you type, based on history and completions.</p>
</li>
<li><p><strong>Syntax highlighting:</strong> Commands are color-coded for better readability.</p>
</li>
<li><p><strong>Out-of-the-box experience:</strong> Works great with minimal configuration, though advanced users can customize via config files or the optional web interface (<code>fish_config</code>).</p>
</li>
<li><p><strong>Modern Engineering:</strong> Version 4.0+ was completely rewritten in Rust for improved performance, memory safety, and long-term maintainability.</p>
</li>
<li><p><strong>Plugin Support:</strong> Tools like Fisher extend Fish's functionality with community plugins.</p>
</li>
<li><p><strong>Important:</strong> Fish is intentionally <strong>not POSIX-compliant</strong>, which makes scripts non-portable to other shells. Use Bash or POSIX sh for portable scripting.</p>
</li>
</ul>
<h2 id="heading-ksh-the-korn-shell">Ksh: The Korn Shell</h2>
<p>Ksh (Korn Shell), originally developed by David Korn at Bell Labs, is a classic choice known for:</p>
<ul>
<li><p><strong>Scripting efficiency:</strong> Often preferred for scripting in large-scale environments.</p>
</li>
<li><p><strong>Compatibility with Bourne shell:</strong> Eases transition for users familiar with traditional Unix shells.</p>
</li>
<li><p><strong>Current Status:</strong> The actively maintained version is <strong>ksh93u+m</strong>, a community-led fork created after AT&amp;T ceased development. The ksh2020 project was abandoned in 2021. For new work with Ksh, use ksh93u+m, which is now packaged in major distributions like Debian and Fedora.</p>
</li>
</ul>
<h2 id="heading-tcsh-an-enhanced-c-shell">Tcsh: An Enhanced C Shell</h2>
<p>Tcsh is an improvement over the traditional C shell (csh), notable for:</p>
<ul>
<li><p><strong>Programming features:</strong> Inherits C shell's syntax, appealing to programmers.</p>
</li>
<li><p><strong>Enhancements:</strong> Offers command-line editing, spell check, and job control.</p>
</li>
</ul>
<h2 id="heading-ash-amp-dash-lightweight-alternatives">Ash &amp; Dash: Lightweight Alternatives</h2>
<p>Ash (Almquist Shell) and Dash (Debian Almquist Shell) are:</p>
<ul>
<li><p><strong>Fast and lightweight:</strong> Ideal for systems with limited resources.</p>
</li>
<li><p><strong>POSIX-compliant:</strong> Ensuring strict compatibility with standards.</p>
</li>
<li><p><strong>Dash's Critical Role:</strong> Dash is the default <strong>system shell</strong> (<code>/bin/sh</code>) on Debian, Ubuntu, and derivatives. It executes system scripts during boot and package management, providing significantly faster performance and lower memory usage than Bash. This makes it essential for system operations, though it's not typically used as an interactive shell.</p>
</li>
<li><p><strong>Use Case:</strong> Dash/Ash are perfect for embedded systems, containers, and system-level scripting where speed and minimal resource usage are priorities.</p>
</li>
</ul>
<h2 id="heading-modern-shells-the-next-generation">Modern Shells: The Next Generation</h2>
<p>A new generation of shells is emerging that challenges traditional Unix text-stream paradigms:</p>
<h3 id="heading-nushell-nu">Nushell (Nu)</h3>
<p>Nushell represents a paradigm shift, treating data as structured tables rather than text streams:</p>
<ul>
<li><p><strong>Structured data:</strong> Commands output tables with columns you can query, sort, and filter natively.</p>
</li>
<li><p><strong>Built-in data format support:</strong> Handles JSON, YAML, CSV, and more without external tools.</p>
</li>
<li><p><strong>Cross-platform:</strong> Consistent experience across Linux, macOS, and Windows.</p>
</li>
<li><p><strong>Modern programming:</strong> Type system with clear error messages and a full-featured scripting language.</p>
</li>
</ul>
<h3 id="heading-elvish">Elvish</h3>
<p>Elvish combines powerful scripting with structured data and functional programming concepts:</p>
<ul>
<li><p><strong>Expressive language:</strong> First-class functions, lexical scoping, and built-in data structures.</p>
</li>
<li><p><strong>Safe scripting:</strong> Exception-based error handling that fails fast instead of continuing silently.</p>
</li>
<li><p><strong>Value-oriented pipelines:</strong> Pass structured data between commands, not just text.</p>
</li>
<li><p><strong>Rich interactive UI:</strong> Built-in navigable history and directory browser.</p>
</li>
</ul>
<p>These modern shells are ideal for users working heavily with APIs, configuration files, and data processing tasks where structured data handling provides significant advantages over traditional text parsing.</p>
<h2 id="heading-choosing-the-right-shell-for-you">Choosing the Right Shell for You</h2>
<p>Selecting a shell depends on your needs:</p>
<ul>
<li><p><strong>Bash</strong> is great for beginners and those seeking broad compatibility and portable scripting.</p>
</li>
<li><p><strong>Zsh</strong> suits users seeking advanced features, extensive customizability, and a rich plugin ecosystem.</p>
</li>
<li><p><strong>Fish</strong> appeals to those desiring a user-friendly, feature-rich experience with minimal configuration.</p>
</li>
<li><p><strong>Ksh</strong> is ideal for maintaining legacy scripts in enterprise Unix environments (use ksh93u+m).</p>
</li>
<li><p><strong>Tcsh</strong> resonates with those who prefer C-like syntax or work in specialized academic/engineering fields.</p>
</li>
<li><p><strong>Dash</strong> is essential for writing fast, POSIX-compliant system scripts on Debian-based systems.</p>
</li>
<li><p><strong>Nushell</strong> is perfect for users working extensively with structured data, APIs, and configuration files.</p>
</li>
<li><p><strong>Elvish</strong> suits programmers who want a shell that behaves like a modern, safe programming language.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Linux shells offer a spectrum of features catering to various user needs. Whether you're a beginner or a seasoned sysadmin, there's a shell that fits your workflow. Experiment with different shells to discover which aligns best with your work style.</p>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li><p>Linux shells vary greatly in features and user experiences, from traditional text-based to modern structured-data shells.</p>
</li>
<li><p>Bash remains the most common interactive shell and is the safe choice for portable scripting.</p>
</li>
<li><p>Many systems use a two-shell strategy: Bash for user interaction and Dash for fast system scripts.</p>
</li>
<li><p>Zsh (now default on macOS) and Fish offer rich ecosystems and excellent interactive experiences.</p>
</li>
<li><p>Modern shells like Nushell and Elvish represent a new paradigm, treating data as structured objects rather than text streams.</p>
</li>
<li><p>When choosing a shell, consider not just features but also the health of its development community and ecosystem.</p>
</li>
</ul>
<p>Remember, the beauty of Linux lies in its versatility, and its shells are a testament to that. Happy exploring!</p>
]]></content:encoded></item></channel></rss>