<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Siddarth</title>
    <description>The latest articles on DEV Community by Siddarth (@siddarth2810).</description>
    <link>https://dev.to/siddarth2810</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2273703%2F53485710-9fa6-4769-b10f-b688febd7042.jpg</url>
      <title>DEV Community: Siddarth</title>
      <link>https://dev.to/siddarth2810</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/siddarth2810"/>
    <language>en</language>
    <item>
      <title>Multi-tenant Loki on Kubernetes</title>
      <dc:creator>Siddarth</dc:creator>
      <pubDate>Wed, 17 Dec 2025 16:44:41 +0000</pubDate>
      <link>https://dev.to/siddarth2810/multi-tenant-loki-on-kubernetes-o17</link>
      <guid>https://dev.to/siddarth2810/multi-tenant-loki-on-kubernetes-o17</guid>
      <description>&lt;p&gt;I'm known as the "monitoring guy" in the company I work at, and this post is about how I deployed Grafana Loki in SimpleScalable mode on Kubernetes and used Promtail to ingest logs per tenant.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Loki ?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Loki is a horizontally scalable, highly available, multi-tenant log aggregation system inspired by Prometheus.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;If you are using Loki for the first time, I highly recommend you to checkout their docs. &lt;a href="https://grafana.com/docs/loki/latest/" rel="noopener noreferrer"&gt;Loki Docs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What we need
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A Loki deployment (SimpleScalable via Helm)&lt;/li&gt;
&lt;li&gt;Promtail&lt;/li&gt;
&lt;li&gt;S3 bucket &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Loki setup (SimpleScalable + S3 storage)
&lt;/h2&gt;

&lt;p&gt;The deployment relies on object storage, so you need a s3 compatible bucket and its credentials to store the logs.&lt;/p&gt;

&lt;p&gt;Our Helm chart is pretty simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;loki-helm-chart/
  ├── templates/
  │   └── loki-secrets.yaml
  ├── Chart.yaml
  └── values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the loki-secrets.yaml would have our s3 credentials secret&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Secret&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-s3-credentials&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monitoring&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Opaque&lt;/span&gt;
&lt;span class="na"&gt;stringData&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;id&amp;gt;"&lt;/span&gt;
  &lt;span class="na"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;access-key&amp;gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Loki values.yaml
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deploymentMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SimpleScalable&lt;/span&gt;

&lt;span class="na"&gt;loki&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;auth_enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;extraEnvFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-s3-credentials&lt;/span&gt;

  &lt;span class="na"&gt;schemaConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2024-04-01"&lt;/span&gt;
        &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tsdb&lt;/span&gt;
        &lt;span class="na"&gt;object_store&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3&lt;/span&gt;
        &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v13&lt;/span&gt;
        &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki_index_&lt;/span&gt;
          &lt;span class="na"&gt;period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24h&lt;/span&gt;

  &lt;span class="na"&gt;storage_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tsdb_shipper&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;index_gateway_client&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;server_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;include&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"loki.indexGatewayAddress"&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;


  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3&lt;/span&gt;
    &lt;span class="na"&gt;s3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rook-ceph-rgw-store.rook-ceph.svc.cluster.local:80&lt;/span&gt;
      &lt;span class="na"&gt;s3ForcePathStyle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;insecure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;


    &lt;span class="na"&gt;bucketNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-logs&lt;/span&gt;
      &lt;span class="na"&gt;ruler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-ruler&lt;/span&gt;
      &lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-admin&lt;/span&gt;


  &lt;span class="na"&gt;commonConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;replication_factor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

  &lt;span class="na"&gt;ingester&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;chunk_encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;snappy&lt;/span&gt;

  &lt;span class="na"&gt;querier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;multi_tenant_queries_enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;max_concurrent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;

  &lt;span class="na"&gt;pattern_ingester&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;limits_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;allow_structured_metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;volume_enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A couple of important notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;auth_enabled: true&lt;/code&gt; means Loki expects a tenant identifier (via &lt;code&gt;X-Scope-OrgID&lt;/code&gt;) for multi-tenancy. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retention in Loki is implemented by the &lt;strong&gt;Compactor&lt;/strong&gt;. If retention isn’t enabled there, logs can live forever even if &lt;code&gt;retention_period&lt;/code&gt; is set. (&lt;a href=""&gt;Log Retention&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rest of the values
&lt;/h3&gt;

&lt;p&gt;Loki components still need local disk for things like &lt;strong&gt;WAL / cache / working state&lt;/strong&gt; so they can perform well. This is why you’ll see PVCs on the read/write/backend pods.&lt;/p&gt;

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

&lt;p&gt;ceph-block is our expandable storage class by the way&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;persistence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Gi&lt;/span&gt;
    &lt;span class="na"&gt;storageClass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ceph-block&lt;/span&gt;
    &lt;span class="na"&gt;accessModes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ReadWriteOnce&lt;/span&gt;
  &lt;span class="na"&gt;extraEnvFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-s3-credentials&lt;/span&gt;

&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;persistence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Gi&lt;/span&gt;
    &lt;span class="na"&gt;storageClass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ceph-block&lt;/span&gt;
    &lt;span class="na"&gt;accessModes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ReadWriteOnce&lt;/span&gt;
  &lt;span class="na"&gt;extraEnvFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-s3-credentials&lt;/span&gt;

&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;extraEnvFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;loki-s3-credentials&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Gateway config (what it does and does not do)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;gateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;customHeaders&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;X-Scope-OrgID&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$http_x_scope_orgid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;strong&gt;does not enforce isolation&lt;/strong&gt; by itself, it just forwards whatever tenant header the caller provides.&lt;/p&gt;

&lt;p&gt;Grafana’s docs recommend that &lt;code&gt;X-Scope-OrgID&lt;/code&gt; be &lt;strong&gt;set by an authenticating reverse proxy&lt;/strong&gt; (so users can’t spoof other tenants). (&lt;a href=""&gt;Grafana Labs&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In my setup, clients do not directly access Loki.&lt;/strong&gt; Only Promtail (inside the cluster) pushes logs, and I control the tenant mapping, so forwarding this header is fine for now.&lt;/p&gt;

&lt;p&gt;Great ! Now moving on to Promtail&lt;/p&gt;

&lt;h2&gt;
  
  
  Promtail setup
&lt;/h2&gt;

&lt;p&gt;Promtail runs on each node and ships container logs to Loki&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;daemonset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;clients&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://loki-gateway.monitoring.svc.cluster.local:80/loki/api/v1/push&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;60s&lt;/span&gt;
      &lt;span class="na"&gt;batchwait&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1s&lt;/span&gt;
      &lt;span class="na"&gt;batchsize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1048576&lt;/span&gt;

  &lt;span class="na"&gt;serverPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3101&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The important part: setting the tenant correctly
&lt;/h3&gt;

&lt;p&gt;I used the Kubernetes namespace into a &lt;code&gt;namespace&lt;/code&gt; label:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;snippets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;common&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;replace&lt;/span&gt;
      &lt;span class="na"&gt;source_labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;__meta_kubernetes_namespace&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;target_label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in the pipeline, set tenant from the &lt;strong&gt;label&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;snippets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelineStages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;tenant&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voila ! we have a multi-tenant Loki setup done.&lt;br&gt;&lt;br&gt;
Now, we can add the Loki data source in Grafana&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F382erh0ntcyx0jir8vav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F382erh0ntcyx0jir8vav.png" alt="Grafana dashboard" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setup &lt;code&gt;X-Scope-OrgID&lt;/code&gt;, I put the value as &lt;code&gt;monitoring&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;And now we will get to &lt;strong&gt;only&lt;/strong&gt; see logs from &lt;code&gt;monitoring&lt;/code&gt; namespace&lt;/p&gt;

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

&lt;p&gt;A HUGEE shoutout to Ben Ye for his help ! &lt;a href="https://github.com/yeya24" rel="noopener noreferrer"&gt;Github Profile Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hope you found this useful. I'm always up for a quick chat, connect with me on &lt;a href="https://www.linkedin.com/in/siddarth2810/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt; or &lt;a href="https://x.com/Siddarth_0910" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>grafana</category>
      <category>telemetry</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>My Linux Kernel Mentorship experience</title>
      <dc:creator>Siddarth</dc:creator>
      <pubDate>Tue, 03 Jun 2025 15:59:19 +0000</pubDate>
      <link>https://dev.to/siddarth2810/my-linux-kernel-mentorship-experience-4870</link>
      <guid>https://dev.to/siddarth2810/my-linux-kernel-mentorship-experience-4870</guid>
      <description>&lt;p&gt;I always loved tweaking around with my computer, trying various Linux distros and window managers. Contributing to the &lt;strong&gt;Linux kernel&lt;/strong&gt; had always been on my bucket list.&lt;/p&gt;

&lt;p&gt;I first heard about the &lt;strong&gt;LFX Mentorship Program&lt;/strong&gt; at &lt;strong&gt;KubeDay India&lt;/strong&gt;, and the idea of Linux kernel bug fixing immediately caught my eye.&lt;/p&gt;

&lt;p&gt;I applied last year but didn’t get in. Fast forward to this year, and when I received the acceptance email, I was literally yelling! It was an unforgettable moment.&lt;/p&gt;

&lt;p&gt;My experience from last year in setting up the kernel build environment helped me finish my tasks a bit quicker this time. It felt like those earlier efforts weren't wasted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mentorship and Community
&lt;/h2&gt;

&lt;p&gt;The program began in March 2025. The initial days involved a lot of learning, diving into videos, blogs, and experiencing a little bit of panic that I hadn't submitted any patches yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Office hours to the rescue!&lt;/strong&gt; Our mentor, Shuah, taught us a lot about the kernel ecosystem, &lt;code&gt;cscope&lt;/code&gt;, Git tips, and how to interpret &lt;code&gt;syzkaller&lt;/code&gt; reports. This was incredibly helpful.&lt;/p&gt;

&lt;p&gt;Being able to talk with fellow mentees and share our learnings in the discord server made a huge difference.&lt;/p&gt;

&lt;p&gt;The greatest part of the Linux community is its vast amount of resources. You truly learn a lot from studying other people’s patches. The &lt;strong&gt;kernel mailing list archives (lore)&lt;/strong&gt; became my bread and butter. Over three months, I went through countless patches from many contributors, which taught me a ton.&lt;/p&gt;

&lt;p&gt;A shout out to &lt;a href="https://github.com/nathanchance" rel="noopener noreferrer"&gt;Nathan Chancellor&lt;/a&gt; and &lt;a href="https://github.com/visitorckw" rel="noopener noreferrer"&gt;Kuan-Wei Chiu&lt;/a&gt; for answering all my questions and for guidance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

&lt;p&gt;Over these 12 weeks, I experimented with various tools and learned many aspects of the kernel. I submitted &lt;strong&gt;13 patches&lt;/strong&gt;, experiencing both successes and rejections.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mindset&lt;/strong&gt;: When my first patch was merged, I hesitated to send similar fixes because I was afraid of harsh feedback. Ironically, those same changes were later sent in by others were accepted. This experience changed my mindset and
I no longer fear making mistakes. Every patch has been a learning experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I once sent a patch to the wrong maintainer &lt;em&gt;(thanks, Zsh autocomplete)&lt;/em&gt;. After making a silly mistake like that, I guess there's no more room to be afraid! :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Writing Good Patches&lt;/strong&gt;: Reading the documentation for the subsystem you’re working on is so important. Always check how patches for that subsystem are being sent in the archives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoiding Churn&lt;/strong&gt;: Avoid sending patches that adds unnecessary noise. When working on a bug it's important to understand where a particular error is coming from and how your fix solves it, and most importantly to test thoroughly!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While my mentorship comes to an end, I still have a lot of things to do and hope to make some significant contributions!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>kernel</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Introduction to Message Brokers: Kafka essentials</title>
      <dc:creator>Siddarth</dc:creator>
      <pubDate>Mon, 10 Feb 2025 20:59:22 +0000</pubDate>
      <link>https://dev.to/siddarth2810/introduction-to-message-brokers-kafka-essentials-3ddk</link>
      <guid>https://dev.to/siddarth2810/introduction-to-message-brokers-kafka-essentials-3ddk</guid>
      <description>&lt;p&gt;Let's say we have a blog website like &lt;strong&gt;Dev.to&lt;/strong&gt;! So, every time a user publishes a blog, the server needs to update the user's blog count in the database. &lt;/p&gt;

&lt;p&gt;With millions of users publishing blogs, API server has to compute and update the DB.&lt;/p&gt;

&lt;p&gt;Isn't that too much of load for the API server ? &lt;br&gt;
&lt;strong&gt;Why not let someone else do this job&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Message Brokers&lt;/strong&gt; come in. Who knows dev.to might also be using these&lt;/p&gt;

&lt;h3&gt;
  
  
  Message Brokers
&lt;/h3&gt;

&lt;p&gt;Instead of the API server directly updating the database, it sends a message to the broker. The broker stores the message in a queue or stream, and worker components process it later.&lt;/p&gt;

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

&lt;p&gt;So our worker component have two jobs in our scenerio&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Updating Count in DB&lt;/li&gt;
&lt;li&gt;Indexing&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How Message Brokers Work
&lt;/h2&gt;

&lt;p&gt;Message brokers can be implemented in two main ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Message Queues (e.g., RabbitMQ, SQS)
&lt;/h3&gt;

&lt;p&gt;In a message queue, messages are stored in a queue and pulled by consumers (workers). For example, a worker might update the blog count in the database and perform indexing.&lt;/p&gt;

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

&lt;p&gt;Once a message goes to one consumer it cannot go to another one.&lt;/p&gt;

&lt;h4&gt;
  
  
  Great! Whats the problem then ?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;What if the worker crashes after updating the database but before indexing? This can lead to inconsistencies and this is why we go for &lt;strong&gt;message streams&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Message Streams (e.g., Kafka, Kinesis)
&lt;/h3&gt;

&lt;p&gt;In message streams like Kafka or Kinesis, messages are loaded into a stream, and consumers process them at their own pace.&lt;/p&gt;

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

&lt;p&gt;Unlike queues, messages are not pulled by consumers. Instead, consumers independently go through the stream and process data.&lt;/p&gt;

&lt;p&gt;This approach ensures better fault tolerance and consistency, as each consumer processes messages independently.&lt;/p&gt;

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

&lt;p&gt;Well this is high level architecture of things, I hope you found this helpful. Thanks for reading :)&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>eventdriven</category>
      <category>kafka</category>
    </item>
    <item>
      <title>Faster Terminal Navigation with Tmux and Fuzzy finder</title>
      <dc:creator>Siddarth</dc:creator>
      <pubDate>Tue, 21 Jan 2025 20:19:23 +0000</pubDate>
      <link>https://dev.to/siddarth2810/faster-terminal-navigation-with-tmux-and-fuzzy-finder-1217</link>
      <guid>https://dev.to/siddarth2810/faster-terminal-navigation-with-tmux-and-fuzzy-finder-1217</guid>
      <description>&lt;p&gt;Using the terminal is one of my favourite things, its just so fasst and its the jam of us linux nerds. &lt;/p&gt;

&lt;p&gt;Buut I've faced with one problem..&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;The Problem: Too Many Terminal Windows&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Yep, In this blog, we'll tackle exactly this. Though there are many workarounds and tools for this but here is what worked for me&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Introducing Tmux: The Terminal Multiplexer&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Gosh I just love this thing! So Tmux is a powerful tool that creates sessions on top of your terminal. Let's just see this in practice&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Installing Tmux&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To get started with Tmux, install it using your favourite package manager. For our lovely linux community just do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;tmux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well windows users can open up WSL i guess..&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Basic Tmux Usage&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Let's walk through the basics of using Tmux:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Open a terminal and type&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The &lt;strong&gt;green bar&lt;/strong&gt; at the bottom indicates that you're in a Tmux session.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fophjk40xuar5o9ngvx1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fophjk40xuar5o9ngvx1a.png" alt="tmux bar" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run the below Python command&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import time; print('Running...'); 
time.sleep(300)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This command just shows &lt;strong&gt;Running...&lt;/strong&gt; for 300 seconds&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbhpf7gpeougpk672ke4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbhpf7gpeougpk672ke4.png" alt="tmux bar" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Now close the Terminal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything seems to be gone, right? Now type the below command&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux attach
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;And Voila!&lt;/strong&gt; We're back in the previous session, exactly where we left off. &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What the heck happened?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tmux runs as a server, so even after you close the terminal, your sessions remain active.&lt;/p&gt;

&lt;p&gt;Some basic Tmux commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;List active sessions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux list-sessions
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a new detached session&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux new-session &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running &lt;code&gt;tmux list-sessions&lt;/code&gt; again: You'll now see two sessions listed.&lt;/p&gt;

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

&lt;p&gt;Once you're in a session, try &lt;code&gt;tmux new-window&lt;/code&gt;. Notice how the asterisk moves to the new window number. &lt;/p&gt;

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

&lt;p&gt;You can create multiple windows this way.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Let's Dive into Tmux Navigation—the Real Power of This Tool!&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The default Tmux prefix key is &lt;code&gt;Ctrl+B&lt;/code&gt;. Here's how to use it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Ctrl+B&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RELEASE BOTH KEYS&lt;/strong&gt; and then press either &lt;code&gt;p&lt;/code&gt; (previous) or &lt;code&gt;n&lt;/code&gt; (next) to switch windows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You have no idea how many times i have failed to do this, releasing the prefix key is so, so important.&lt;/p&gt;

&lt;p&gt;I have spent a lot of time cursing tmux and figuring out why in the world it was not working because of this dumb mistake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's Take It to the Next Level&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;find ~/.config ~/personal ~/courses &lt;span class="nt"&gt;-mindepth&lt;/span&gt; 1 &lt;span class="nt"&gt;-maxdepth&lt;/span&gt; 1 &lt;span class="nt"&gt;-type&lt;/span&gt; d | fzf&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;session_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; _&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; tmux has-session &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then 
    &lt;/span&gt;tmux new-session &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="k"&gt;fi 
&lt;/span&gt;tmux switch-client &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$session_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For my zsh folks, the first line might be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So are my three frequently used folders – &lt;strong&gt;personal&lt;/strong&gt;, &lt;strong&gt;courses&lt;/strong&gt;, and &lt;strong&gt;.config&lt;/strong&gt; – our bash script utilizes &lt;strong&gt;fzf (fuzzy finder)&lt;/strong&gt; to quickly find the desired folder and then creates a new Tmux session if one doesn't already exist.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Integrate with Your Terminal&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Add a shortcut in your shell configuration (e.g., &lt;code&gt;.zshrc&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt;) so that you can run the script quickly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bindkey &lt;span class="nt"&gt;-s&lt;/span&gt; ^f &lt;span class="s2"&gt;"/home/&amp;lt;username&amp;gt;/session.sh&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; with your actual username. This example binds the script to &lt;strong&gt;Ctrl+F&lt;/strong&gt;, giving you instant access to your Tmux sessions.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  &lt;strong&gt;Wrapping Up&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;I personally found this very helpful. I have like a super fast workflow now and really love using this.&lt;/p&gt;

&lt;p&gt;Thank you so much for reading. You're Awesome!&lt;/p&gt;

&lt;p&gt;You can check out my Tmux config &lt;a href="https://github.com/siddarth2810/.dotfiles/blob/main/tmux/tmux.conf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Sources&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://theprimeagen.github.io/dev-productivity/shell" rel="noopener noreferrer"&gt;The Primeagen's Dev Productivity Shell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>tmux</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
