<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Karan Sharma - Posts</title>
    <subtitle>Ramblings on programming, tech and life.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://mrkaran.dev/posts/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-12T00:00:00+00:00</updated>
    <id>https://mrkaran.dev/posts/atom.xml</id>
    <entry xml:lang="en">
        <title>Building an LLM-Assisted Incident Investigation Tool</title>
        <published>2026-03-12T00:00:00+00:00</published>
        <updated>2026-03-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/pi-sre-mode/"/>
        <id>https://mrkaran.dev/posts/pi-sre-mode/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/pi-sre-mode/">&lt;p&gt;When you are debugging a production incident, you are forming hypotheses, testing them against evidence, ruling things out, trying not to confuse correlation with causation, and making triage calls under time pressure. The hard part is the reasoning – figuring out &lt;em&gt;why&lt;&#x2F;em&gt; the system is misbehaving, deciding what to stabilize first, knowing when to stop chasing a red herring.&lt;&#x2F;p&gt;
&lt;p&gt;But a surprising amount of the &lt;em&gt;time&lt;&#x2F;em&gt; is not spent reasoning. It is spent gathering evidence.&lt;&#x2F;p&gt;
&lt;p&gt;You are flipping between your metrics dashboard, log viewer, scheduler, cloud console, SSH sessions, deployment history, and a half-written scratchpad. You are trying to answer questions that are conceptually simple but operationally expensive:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What changed in the last hour?&lt;&#x2F;li&gt;
&lt;li&gt;Did the error spike start before or after the deploy?&lt;&#x2F;li&gt;
&lt;li&gt;Is this one sick node or a fleet-wide regression?&lt;&#x2F;li&gt;
&lt;li&gt;Did the autoscaling event line up with the HAProxy alert?&lt;&#x2F;li&gt;
&lt;li&gt;Are we looking at cause, effect, or a noisy side symptom?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each question requires pulling data from a different tool, in a different format, often with timestamps in different timezones. Then you stitch them into a timeline before you can even begin hypothesizing.&lt;&#x2F;p&gt;
&lt;p&gt;That evidence-gathering phase is where LLMs turned out to be useful for me. Not because they “solve incidents” – the hypothesis formation, the triage, the mitigation calls stay human. But an LLM with access to the right CLIs can chew through the data-gathering faster than I can by hand.&lt;&#x2F;p&gt;
&lt;p&gt;I took the system I’d been building internally and rebuilt it as a package for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pi.dev&#x2F;&quot;&gt;Pi&lt;&#x2F;a&gt; – a minimal, extensible terminal coding agent – called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;pi-sre-mode&quot;&gt;&lt;code&gt;pi-sre-mode&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This post is about the journey from a custom agent platform to a thin extension, and why the value turned out to live in content, not code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-predecessor-llmduck&quot;&gt;The Predecessor: llmduck&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-predecessor-llmduck&quot; aria-label=&quot;Anchor link for: the-predecessor-llmduck&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before &lt;code&gt;pi-sre-mode&lt;&#x2F;code&gt;, I had a system called &lt;code&gt;llmduck&lt;&#x2F;code&gt;. It went through several rewrites – first in Go, then partially in Rust, and finally as a full TypeScript web application with a server (LLM orchestration, session persistence, WebSocket dispatch), a remote agent (command execution on production hosts with policy enforcement), and a React frontend with a split-panel investigation UI.&lt;&#x2F;p&gt;
&lt;p&gt;The agent had one tool: &lt;code&gt;bash&lt;&#x2F;code&gt;. All infrastructure interaction happened through CLIs – metrics, logs, scheduler state, cloud APIs, SSH. The LLM decided what to run, the agent executed it, and the server tracked the conversation. An SRE methodology skill guided the model through a structured investigation loop: triage, scope, gather evidence across metrics&#x2F;logs&#x2F;scheduling, correlate, conclude.&lt;&#x2F;p&gt;
&lt;p&gt;It worked. Give the model good operational guidance and read-only access to the right CLIs, and it can do a lot of the mechanical data gathering that normally burns 20-40 minutes during an incident. It can compare scheduler restarts with metric trends. It can correlate a failing backend with a cloud autoscaling event. It can notice that one host is missing metrics entirely and that the “healthy” cluster is only healthy because the remaining nodes are absorbing the load.&lt;&#x2F;p&gt;
&lt;p&gt;But the runtime was increasingly the wrong abstraction.&lt;&#x2F;p&gt;
&lt;p&gt;I had a custom server, a custom agent, a custom frontend, custom registries for skills and templates, custom session persistence, and a CI pipeline to build and deploy it all. The upstream&#x2F;wrapper two-repo design – where the generic product lived on GitHub and the org-specific overlay was rsynced into it during build – still meant I was maintaining a bespoke investigation platform.&lt;&#x2F;p&gt;
&lt;p&gt;The more I worked on it, the more obvious it became: &lt;strong&gt;the content was the product. The runtime was plumbing.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The skills, the prompts, the methodology, the failure pattern library, the runbooks, the templates – that was where the value lived. Everything else was infrastructure I was maintaining just to get those skills into an LLM session.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-pi&quot;&gt;Why Pi&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-pi&quot; aria-label=&quot;Anchor link for: why-pi&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I did not want another chat app. I wanted the investigation to live where I already work: in the terminal, next to the real tools. Pi gave me that, and the specific SDK primitives it exposes turned out to map almost 1:1 to what I had been building by hand in llmduck.&lt;&#x2F;p&gt;
&lt;p&gt;A session looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;check-connectors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;incident&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;investigate elevated p99 latency for payments-api, start with a timeline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;report&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;&#x2F;incident&lt;&#x2F;code&gt; is an interactive wizard – pick a template, name the service, set a time window.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;pi-sre-investigate.png&quot; alt=&quot;The &#x2F;incident wizard showing template selection&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;check-connectors&lt;&#x2F;code&gt; – verifies your infrastructure CLIs are reachable&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;report&lt;&#x2F;code&gt; – generates a structured postmortem from the investigation&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;sudo&lt;&#x2F;code&gt; – temporarily bypasses the read-only guardrails&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-it-works&quot; aria-label=&quot;Anchor link for: how-it-works&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Pi extensions are TypeScript modules that receive an &lt;code&gt;ExtensionAPI&lt;&#x2F;code&gt; object – hooks into the agent lifecycle, slash commands, session state, shell execution, UI primitives, and an inter-extension event bus. The whole extension is one file and the rest is markdown.&lt;&#x2F;p&gt;
&lt;p&gt;The SDK has a few primitives that matter here:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;carrying-context-across-the-conversation&quot;&gt;Carrying context across the conversation&lt;a class=&quot;zola-anchor&quot; href=&quot;#carrying-context-across-the-conversation&quot; aria-label=&quot;Anchor link for: carrying-context-across-the-conversation&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;before_agent_start&lt;&#x2F;code&gt; hook fires before every agent turn. The extension builds a context block from the current incident state and appends it to the system prompt:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pi&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;before_agent_start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; systemPrompt&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;event&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;systemPrompt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;incidentContext&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Template, service name, time window, guardrail posture, overlay guidance, preferred skills – all injected automatically. You do not need to keep re-explaining “payments API, last 2 hours, high latency, read-only.” It follows you.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;blocking-mutations-before-they-execute&quot;&gt;Blocking mutations before they execute&lt;a class=&quot;zola-anchor&quot; href=&quot;#blocking-mutations-before-they-execute&quot; aria-label=&quot;Anchor link for: blocking-mutations-before-they-execute&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;tool_call&lt;&#x2F;code&gt; hook intercepts every tool invocation before execution:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pi&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;tool_call&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; async&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; reason&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; getGuardrailBlockReason&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;event&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;toolName&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;input&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;reason&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; block&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The guardrail implementation is regex-based with token boundary detection:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; BLOCKED_PATTERNS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sudo blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;file deletion blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;kill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pkill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;killall&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;process termination blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bash&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;zsh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;shell trampoline blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eval&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eval blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);font-weight: bold;&quot;&gt;\$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);font-weight: bold;&quot;&gt;\(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;subshell blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;restart&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;stop&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;systemctl mutation blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span&gt; pattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;create&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;delete&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;update&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;put&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;stop&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;terminate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;reboot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;AWS mutation blocked&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The token boundary prevents false positives – &lt;code&gt;remove&lt;&#x2F;code&gt; does not match the &lt;code&gt;rm&lt;&#x2F;code&gt; rule. The &lt;code&gt;write&lt;&#x2F;code&gt; and &lt;code&gt;edit&lt;&#x2F;code&gt; tools are unconditionally blocked. &lt;code&gt;&#x2F;sudo&lt;&#x2F;code&gt; disables this when needed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;persisting-incident-state&quot;&gt;Persisting incident state&lt;a class=&quot;zola-anchor&quot; href=&quot;#persisting-incident-state&quot; aria-label=&quot;Anchor link for: persisting-incident-state&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Pi sessions are tree-structured – you can fork, navigate branches, switch contexts. Incident state is persisted as append-only entries:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pi&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;appendEntry&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;IncidentModeState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;incident-mode-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The extension hooks into &lt;code&gt;session_tree&lt;&#x2F;code&gt; and &lt;code&gt;session_fork&lt;&#x2F;code&gt; events to carry incident state across branches automatically. If you fork to explore a side hypothesis, the incident context comes with you.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;commands-and-ui&quot;&gt;Commands and UI&lt;a class=&quot;zola-anchor&quot; href=&quot;#commands-and-ui&quot; aria-label=&quot;Anchor link for: commands-and-ui&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;pi.registerCommand()&lt;&#x2F;code&gt; handles slash commands. The &lt;code&gt;&#x2F;incident&lt;&#x2F;code&gt; wizard uses &lt;code&gt;ctx.ui.select()&lt;&#x2F;code&gt; and &lt;code&gt;ctx.ui.input()&lt;&#x2F;code&gt; for interactive setup – template selection, service name, time window. &lt;code&gt;pi.exec()&lt;&#x2F;code&gt; runs shell commands for connector checks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;inter-extension-events&quot;&gt;Inter-extension events&lt;a class=&quot;zola-anchor&quot; href=&quot;#inter-extension-events&quot; aria-label=&quot;Anchor link for: inter-extension-events&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Pi has an in-process event bus (&lt;code&gt;pi.events&lt;&#x2F;code&gt;) for cross-package communication – same JS runtime, no network, just pub&#x2F;sub between extensions loaded from different npm packages. The base package subscribes to a channel, the overlay emits to it at session start. The decoupling is at the import level, not the process level. More on this below.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;templates-and-skills&quot;&gt;Templates and Skills&lt;a class=&quot;zola-anchor&quot; href=&quot;#templates-and-skills&quot; aria-label=&quot;Anchor link for: templates-and-skills&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Most incidents fall into a handful of patterns – 5xx spike, high latency, OOM crash loop, deploy regression, service down. Each pattern has a different starting point: for latency you want percentile breakdowns and dependency response times first; for OOMs you want restart history and memory growth; for a deploy regression you want a before&#x2F;after comparison.&lt;&#x2F;p&gt;
&lt;p&gt;Templates encode that. When you pick “High Latency” in the &lt;code&gt;&#x2F;incident&lt;&#x2F;code&gt; wizard, the system prompt gets a focused directive: check p50&#x2F;p95&#x2F;p99, look for saturation signals, check upstream dependencies, identify whether queueing is involved. The model starts in the right place instead of flailing. You can also skip the wizard entirely – &lt;code&gt;&#x2F;incident-5xx payments-api last 2h&lt;&#x2F;code&gt; sets up the investigation directly.&lt;&#x2F;p&gt;
&lt;p&gt;The investigation methodology itself lives in skills – markdown files that get loaded into context:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;re-methodology&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;llowed-tools&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ead&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rep&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);font-weight: bold;&quot;&gt;##&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);font-weight: bold;&quot;&gt; Core Loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;1.&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; **&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Observe&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;: Gather data. Metrics, logs, scheduler state.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; **&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Hypothesize&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;: Form a theory from the evidence.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;3.&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; **&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Test&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;: Run a specific query that would confirm or disprove.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;4.&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; **&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Evaluate&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;: Did the evidence match? Adjust and repeat.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The base package includes two skills: an observe-hypothesize-test-evaluate loop with first principles (evidence over speculation, build timeline before concluding, the loudest symptom is often downstream), and a concrete investigation playbook (scope the blast radius, check recent changes, follow the service path from edge to dependency, narrow using the template focus).&lt;&#x2F;p&gt;
&lt;p&gt;Without the methodology, the model tends to jump to conclusions or fixate on the noisiest symptom. With it, investigations are more systematic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-overlay-system&quot;&gt;The Overlay System&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-overlay-system&quot; aria-label=&quot;Anchor link for: the-overlay-system&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The public package is intentionally generic. The real leverage comes from &lt;strong&gt;overlays&lt;&#x2F;strong&gt; – private Pi packages that layer org-specific knowledge on top.&lt;&#x2F;p&gt;
&lt;p&gt;An overlay is a separate Pi package that emits an event at session start. The base package picks it up and merges it into the active configuration – templates, connector checks, skills, timezone hints, report output paths:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; function&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; myOrgOverlay&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F69D50);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;pi&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; ExtensionAPI&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F69D50);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; overlay&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; IncidentOverlay&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;my-org&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    priority&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    timezoneHint&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;IST (UTC+5:30); metrics are UTC, logs are IST.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reportPathPattern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rca&#x2F;{{date}}-{{slug}}.md&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    defaultSkills&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;org-sre-methodology&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    promptPreamble&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Use org service topology, strict timezone handling...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    connectorChecks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    templates&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  pi&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;session_start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pi&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;emit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;incident-mode:register-overlay&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; overlay&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Templates merge by ID (overlay wins). Skills are deduplicated. Prompt preambles stack across overlays.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-an-overlay-adds&quot;&gt;What an Overlay Adds&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-an-overlay-adds&quot; aria-label=&quot;Anchor link for: what-an-overlay-adds&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;At work, my private overlay adds investigation templates tied to specific services and a few thousand lines of operational knowledge as skills – how to query our metrics stack, how to read our logs, how to interpret scheduler state, and how to write the postmortem.&lt;&#x2F;p&gt;
&lt;p&gt;The interesting part is what those skills encode. Not just CLI syntax, but the gotchas you learn the hard way: timezone mismatches between tools, CPU metrics that mean something different depending on allocation config, log columns that don’t exist where you’d expect them, query patterns that accidentally match unrelated data. A failure pattern library teaches the model to recognize cascading failures, throughput cliffs (silence often means blocked, not recovered), and the difference between a root cause and a downstream symptom.&lt;&#x2F;p&gt;
&lt;p&gt;This is the kind of institutional knowledge that normally lives in someone’s head or a stale wiki page. Encoding it as skills means it gets applied consistently during every investigation.&lt;&#x2F;p&gt;
&lt;p&gt;Every team has different tools, naming conventions, auth assumptions, and definitions of “normal.” Mix that into the base package and you either leak private knowledge or make the tool unusably abstract. The overlay keeps them cleanly separated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-the-llm-is-actually-good-at&quot;&gt;What the LLM Is Actually Good At&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-the-llm-is-actually-good-at&quot; aria-label=&quot;Anchor link for: what-the-llm-is-actually-good-at&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is not an “AI will run your ops team” post. The model does not do triage or make mitigation calls. What it does well is the stuff that eats wall-clock time:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gathering-and-cross-referencing-evidence&quot;&gt;Gathering and cross-referencing evidence&lt;a class=&quot;zola-anchor&quot; href=&quot;#gathering-and-cross-referencing-evidence&quot; aria-label=&quot;Anchor link for: gathering-and-cross-referencing-evidence&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The model does not stop at “good enough.” If you ask it to investigate a latency spike, it will check p50&#x2F;p95&#x2F;p99, break it down per node, compare against the pre-deploy baseline, look at upstream dependency latency, check if the error rate moved with it, and then go look at logs for the time window where the percentiles diverged.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;building-timelines-from-messy-evidence&quot;&gt;Building timelines from messy evidence&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-timelines-from-messy-evidence&quot; aria-label=&quot;Anchor link for: building-timelines-from-messy-evidence&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The model is good at stitching together outputs from different tools – logs in IST, metrics in UTC, a deploy at some offset, a scheduler restart in the middle, a cloud instance termination, a queue backup two minutes later – into a coherent narrative. It can produce a first-pass timeline like “memory growth started after deploy X, restart happened 14 minutes later, error rate rose only on one node, autoscaling replaced the sick instance, and downstream proxy alerts were a secondary symptom” faster than I can by hand.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;producing-a-first-draft-of-the-postmortem&quot;&gt;Producing a first draft of the postmortem&lt;a class=&quot;zola-anchor&quot; href=&quot;#producing-a-first-draft-of-the-postmortem&quot; aria-label=&quot;Anchor link for: producing-a-first-draft-of-the-postmortem&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The postmortem is hardest to write right after the incident, precisely when it is most valuable. If the investigation happened inside Pi, &lt;code&gt;&#x2F;report&lt;&#x2F;code&gt; turns the conversation into a structured markdown RCA draft immediately – timeline, 5 Whys, impact, action items. That alone saves a lot of the “I’ll write the postmortem tomorrow” drift.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;keeping-the-investigation-disciplined&quot;&gt;Keeping the investigation disciplined&lt;a class=&quot;zola-anchor&quot; href=&quot;#keeping-the-investigation-disciplined&quot; aria-label=&quot;Anchor link for: keeping-the-investigation-disciplined&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The methodology skills help the model stay in evidence-first mode: observe before hypothesizing, build a timeline before concluding, distinguish cause from effect, state uncertainty explicitly, say when a connector is missing instead of guessing. Without this, the model tends to fixate on the noisiest symptom. With it, investigations follow an observe-hypothesize-test-evaluate loop.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-it-still-fails&quot;&gt;Where It Still Fails&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-it-still-fails&quot; aria-label=&quot;Anchor link for: where-it-still-fails&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;guardrails-are-not-a-sandbox&quot;&gt;Guardrails are not a sandbox&lt;a class=&quot;zola-anchor&quot; href=&quot;#guardrails-are-not-a-sandbox&quot; aria-label=&quot;Anchor link for: guardrails-are-not-a-sandbox&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The read-only protections are operational guardrails, not security boundaries. They catch accidental mutations during investigation, but they are regex patterns – not a sandbox. The real defense is least-privilege at the infrastructure level: an AWS IAM role scoped to read-only, a metrics API token without write access, an SSH key that can only reach jump hosts. If the credentials the agent has cannot mutate anything, it does not matter if a guardrail regex gets bypassed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-model-can-still-hallucinate&quot;&gt;The model can still hallucinate&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-model-can-still-hallucinate&quot; aria-label=&quot;Anchor link for: the-model-can-still-hallucinate&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It will sometimes invent a metric name, over-index on a noisy symptom, or keep running commands when the evidence is already sufficient. Good skills help but do not make it reliable enough to trust unattended.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-bigger-lesson&quot;&gt;The Bigger Lesson&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-bigger-lesson&quot; aria-label=&quot;Anchor link for: the-bigger-lesson&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I spent weeks building and rebuilding a custom agent platform. Rewrote it twice in different languages. All plumbing. The things that actually made the investigations good were:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the SRE methodology skill that encoded how to think about incidents&lt;&#x2F;li&gt;
&lt;li&gt;the failure pattern library that taught the model to recognize cascade failures and throughput cliffs&lt;&#x2F;li&gt;
&lt;li&gt;the per-tool skills that encoded gotchas like “that CPU metric means something different in a cgroup” and “silence in the logs means blocked, not recovered”&lt;&#x2F;li&gt;
&lt;li&gt;the templates that seeded the investigation direction&lt;&#x2F;li&gt;
&lt;li&gt;the guardrails that kept the model from accidentally mutating production&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All of those are markdown files and a few dozen regex patterns. I kept building runtime to deliver content. Once I had a platform that could host markdown skills and intercept tool calls, the custom stack had no reason to exist.&lt;&#x2F;p&gt;
&lt;p&gt;The code is at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;pi-sre-mode&quot;&gt;github.com&#x2F;mr-karan&#x2F;pi-sre-mode&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Web Terminal for My Homelab with ttyd + tmux</title>
        <published>2026-03-05T00:00:00+00:00</published>
        <updated>2026-03-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/web-terminal-homelab/"/>
        <id>https://mrkaran.dev/posts/web-terminal-homelab/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/web-terminal-homelab/">&lt;p&gt;I wanted a browser terminal at &lt;code&gt;terminal.mrkaran.dev&lt;&#x2F;code&gt; that works from laptop, tablet, and phone without special client setup.&lt;&#x2F;p&gt;
&lt;p&gt;The stack that works cleanly for this is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tsl0922&#x2F;ttyd&quot;&gt;ttyd&lt;&#x2F;a&gt; + tmux.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;a class=&quot;zola-anchor&quot; href=&quot;#architecture&quot; aria-label=&quot;Anchor link for: architecture&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Browser -&amp;gt; Caddy -&amp;gt; ttyd -&amp;gt; nsenter -&amp;gt; su - karan -&amp;gt; tmux(main)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Two decisions matter most:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;ttyd&lt;&#x2F;code&gt; handles terminal-over-websocket behavior well.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-m 1&lt;&#x2F;code&gt; enforces a single active client, which avoids cross-tab resize contention.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;docker-compose-current&quot;&gt;Docker Compose (current)&lt;a class=&quot;zola-anchor&quot; href=&quot;#docker-compose-current&quot; aria-label=&quot;Anchor link for: docker-compose-current&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ebterm&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sl0922&#x2F;ttyd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ontainer_name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ebterm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;estart&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nless-stopped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      ttyd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        -W&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        -p 8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        -m 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        nsenter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        -t 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        -m -u -i -p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        --&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        su - karan -c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;tmux new-session -A -s main&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rivileged&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ublic_proxy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Why each flag matters:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-W&lt;&#x2F;code&gt;: writable shell&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-p 8080&lt;&#x2F;code&gt;: matches my existing Caddy upstream (&lt;code&gt;webterm:8080&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-m 1&lt;&#x2F;code&gt;: one active client only (no resize fight club)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;nsenter ...&lt;&#x2F;code&gt;: real host shell from inside the container&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;su - karan&lt;&#x2F;code&gt;: correct login environment and tmux config loading&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;tmux new-session -A -s main&lt;&#x2F;code&gt;: persistent attach&#x2F;re-attach&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;caddy&quot;&gt;Caddy&lt;a class=&quot;zola-anchor&quot; href=&quot;#caddy&quot; aria-label=&quot;Anchor link for: caddy&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;terminal.mrkaran.dev&lt;&#x2F;code&gt; reverse proxies to &lt;code&gt;webterm:8080&lt;&#x2F;code&gt; with TLS via Cloudflare DNS challenge.
Because ttyd uses WebSockets heavily, reverse proxy support for upgrades is essential.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tmux-profile-for-agentic-workflows&quot;&gt;tmux profile for agentic workflows&lt;a class=&quot;zola-anchor&quot; href=&quot;#tmux-profile-for-agentic-workflows&quot; aria-label=&quot;Anchor link for: tmux-profile-for-agentic-workflows&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I tuned tmux for long-running agent sessions, not just manual shell use.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;long-run-defaults&quot;&gt;Long-run defaults&lt;a class=&quot;zola-anchor&quot; href=&quot;#long-run-defaults&quot; aria-label=&quot;Anchor link for: long-run-defaults&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;history-limit 200000&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;remain-on-exit on&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;window-size latest&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mode-keys vi&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;status-keys vi&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;better-operational-visibility&quot;&gt;Better operational visibility&lt;a class=&quot;zola-anchor&quot; href=&quot;#better-operational-visibility&quot; aria-label=&quot;Anchor link for: better-operational-visibility&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;status line shows host + session + path + time&lt;&#x2F;li&gt;
&lt;li&gt;pane border shows pane number + current command&lt;&#x2F;li&gt;
&lt;li&gt;active pane is clearly highlighted&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;keybinds-i-actually-use&quot;&gt;Keybinds I actually use&lt;a class=&quot;zola-anchor&quot; href=&quot;#keybinds-i-actually-use&quot; aria-label=&quot;Anchor link for: keybinds-i-actually-use&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Prefix: &lt;code&gt;Ctrl-b&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;S&lt;&#x2F;code&gt;: create&#x2F;attach named session&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;N&lt;&#x2F;code&gt;: create named window&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;R&lt;&#x2F;code&gt;: rename window&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;s&lt;&#x2F;code&gt;: session&#x2F;window picker&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;y&lt;&#x2F;code&gt;: toggle &lt;code&gt;synchronize-panes&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;h&#x2F;j&#x2F;k&#x2F;l&lt;&#x2F;code&gt;: pane movement&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;H&#x2F;J&#x2F;K&#x2F;L&lt;&#x2F;code&gt;: pane resize&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;copy-paste-that-is-not-annoying&quot;&gt;Copy&#x2F;paste that is not annoying&lt;a class=&quot;zola-anchor&quot; href=&quot;#copy-paste-that-is-not-annoying&quot; aria-label=&quot;Anchor link for: copy-paste-that-is-not-annoying&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This was a big pain point, so I added both workflows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Browser-native copy&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ctrl-b m&lt;&#x2F;code&gt; to turn tmux mouse &lt;strong&gt;off&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;drag-select + browser copy shortcut&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Ctrl-b m&lt;&#x2F;code&gt; to turn tmux mouse back &lt;strong&gt;on&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;tmux copy mode&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ctrl-b [&lt;&#x2F;code&gt; enters copy mode and shows &lt;code&gt;COPY MODE ON&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;v&lt;&#x2F;code&gt; select, &lt;code&gt;y&lt;&#x2F;code&gt; copy (shows &lt;code&gt;Copied selection&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;q&lt;&#x2F;code&gt; or &lt;code&gt;Esc&lt;&#x2F;code&gt; exits (shows &lt;code&gt;COPY MODE OFF&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;On mobile, ttyd’s top-left menu (special keys) makes prefix navigation workable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;security-model&quot;&gt;Security model&lt;a class=&quot;zola-anchor&quot; href=&quot;#security-model&quot; aria-label=&quot;Anchor link for: security-model&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is tailnet-only behind Tailscale. No public exposure.&lt;&#x2F;p&gt;
&lt;p&gt;Still, the container has &lt;code&gt;privileged: true&lt;&#x2F;code&gt; and &lt;code&gt;pid: host&lt;&#x2F;code&gt;, which is a strong trust boundary.
If you expose anything like this publicly, add auth in front and treat it as high-risk infrastructure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;result&quot;&gt;Result&lt;a class=&quot;zola-anchor&quot; href=&quot;#result&quot; aria-label=&quot;Anchor link for: result&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;web-terminal-homelab.png&quot; alt=&quot;Web terminal in the browser&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The terminal is now boring in the best way: stable, predictable, and fast to reach from any device.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Setting Up LiteLLM with AWS Bedrock</title>
        <published>2026-02-16T00:00:00+00:00</published>
        <updated>2026-02-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/litellm-bedrock-setup/"/>
        <id>https://mrkaran.dev/posts/litellm-bedrock-setup/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/litellm-bedrock-setup/">&lt;p&gt;I recently set up &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BerriAI&#x2F;litellm&quot;&gt;LiteLLM&lt;&#x2F;a&gt; with AWS Bedrock as the LLM provider. The docs cover the happy path, but there are a few gotchas that cost me some debugging time. This post covers what I learned, from basic setup to per-project cost tracking with Application Inference Profiles.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;model-format&quot;&gt;Model Format&lt;a class=&quot;zola-anchor&quot; href=&quot;#model-format&quot; aria-label=&quot;Anchor link for: model-format&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Bedrock models use the &lt;code&gt;bedrock&#x2F;&lt;&#x2F;code&gt; prefix followed by AWS’s model identifiers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bedrock&#x2F;anthropic.claude-opus-4-6-v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bedrock&#x2F;anthropic.claude-sonnet-4-5-20250929-v1:0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nothing surprising here. LiteLLM uses the prefix to route to the right provider.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authentication&quot;&gt;Authentication&lt;a class=&quot;zola-anchor&quot; href=&quot;#authentication&quot; aria-label=&quot;Anchor link for: authentication&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is where the first gotcha lives. Bedrock doesn’t use API keys. It authenticates via standard AWS credentials:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Environment variables: &lt;code&gt;AWS_ACCESS_KEY_ID&lt;&#x2F;code&gt; + &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;AWS profile: &lt;code&gt;AWS_PROFILE&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;IAM role (for EC2&#x2F;ECS&#x2F;Lambda)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You also need &lt;code&gt;AWS_REGION_NAME&lt;&#x2F;code&gt; set to the region where Bedrock is enabled (e.g., &lt;code&gt;ap-south-1&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The gotcha&lt;&#x2F;strong&gt;: don’t pass &lt;code&gt;api_key&lt;&#x2F;code&gt; to LiteLLM when using Bedrock. If you include an &lt;code&gt;api_key&lt;&#x2F;code&gt; parameter in your config, LiteLLM tries to use it instead of the AWS credential chain and auth fails silently. You need to either return &lt;code&gt;None&lt;&#x2F;code&gt; for the API key or omit it from the config entirely.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Wrong - breaks AWS credential chain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;llm_config&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;model&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bedrock&#x2F;anthropic.claude-opus-4-6-v1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;api_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; some_key&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Correct - let LiteLLM use AWS credentials&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;llm_config&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;model&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bedrock&#x2F;anthropic.claude-opus-4-6-v1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This one took a while to figure out because the error messages don’t point you in the right direction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-top-p-and-temperature-conflict&quot;&gt;The &lt;code&gt;top_p&lt;&#x2F;code&gt; and Temperature Conflict&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-top-p-and-temperature-conflict&quot; aria-label=&quot;Anchor link for: the-top-p-and-temperature-conflict&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Bedrock’s Anthropic models reject requests that include both &lt;code&gt;temperature&lt;&#x2F;code&gt; and &lt;code&gt;top_p&lt;&#x2F;code&gt;. If your SDK or framework defaults &lt;code&gt;top_p=1.0&lt;&#x2F;code&gt;, you need to explicitly clear it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; model&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;startswith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bedrock&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    llm_config&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;top_p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Without this, you’ll get a validation error from the Bedrock API. The fix is simple, but the error message isn’t immediately obvious about what’s conflicting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inference-profiles&quot;&gt;Inference Profiles&lt;a class=&quot;zola-anchor&quot; href=&quot;#inference-profiles&quot; aria-label=&quot;Anchor link for: inference-profiles&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Bedrock has two types of inference profiles, and the second one is where things get interesting for cost management.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cross-region-system-defined&quot;&gt;Cross-Region (System-Defined)&lt;a class=&quot;zola-anchor&quot; href=&quot;#cross-region-system-defined&quot; aria-label=&quot;Anchor link for: cross-region-system-defined&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;AWS provides these out of the box. They route requests across regions for higher throughput and availability:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;global.anthropic.claude-opus-4-6-v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can list them with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; bedrock&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; list-inference-profiles&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-type-equals&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; SYSTEM_DEFINED&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-region&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ap-south-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;application-inference-profiles-for-cost-tracking&quot;&gt;Application Inference Profiles for Cost Tracking&lt;a class=&quot;zola-anchor&quot; href=&quot;#application-inference-profiles-for-cost-tracking&quot; aria-label=&quot;Anchor link for: application-inference-profiles-for-cost-tracking&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Application Inference Profiles (AIPs) are tagged wrappers around a model. The killer use case is &lt;strong&gt;granular cost attribution&lt;&#x2F;strong&gt; via cost allocation tags. Instead of seeing one blob of “Bedrock spend” in your AWS bill, you can break it down by project, team, or service.&lt;&#x2F;p&gt;
&lt;p&gt;Create one with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; bedrock&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; create-inference-profile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-inference-profile-name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; my-project-opus-4-6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-model-source&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;copyFrom=arn:aws:bedrock:ap-south-1::foundation-model&#x2F;anthropic.claude-opus-4-6-v1:0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; key=project,value=my-project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-region&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ap-south-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This gives you an ARN like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;arn:aws:bedrock:ap-south-1:123456789012:application-inference-profile&#x2F;abcdef123456&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;using-aips-with-litellm&quot;&gt;Using AIPs with LiteLLM&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-aips-with-litellm&quot; aria-label=&quot;Anchor link for: using-aips-with-litellm&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The standard &lt;code&gt;bedrock&#x2F;&lt;&#x2F;code&gt; route can’t parse ARNs. Use the &lt;code&gt;bedrock&#x2F;converse&#x2F;&lt;&#x2F;code&gt; route instead:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bedrock&#x2F;converse&#x2F;arn:aws:bedrock:ap-south-1:123456789012:application-inference-profile&#x2F;abcdef123456&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;bedrock&#x2F;&lt;&#x2F;code&gt; prefix still matches for provider detection and the &lt;code&gt;top_p=None&lt;&#x2F;code&gt; fix, so no code changes needed on your end.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;querying-costs-via-cli&quot;&gt;Querying Costs via CLI&lt;a class=&quot;zola-anchor&quot; href=&quot;#querying-costs-via-cli&quot; aria-label=&quot;Anchor link for: querying-costs-via-cli&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Once your AIPs are tagged, you can query costs using the Cost Explorer API.&lt;&#x2F;p&gt;
&lt;p&gt;Total Bedrock spend for a month:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ce&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get-cost-and-usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-time-period&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Start=2026-02-01,End=2026-03-01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-granularity&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MONTHLY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-metrics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;UnblendedCost&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-filter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&amp;quot;Dimensions&amp;quot;: {&amp;quot;Key&amp;quot;: &amp;quot;SERVICE&amp;quot;, &amp;quot;Values&amp;quot;: [&amp;quot;Amazon Bedrock&amp;quot;]}}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-region&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; us-east-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Bedrock spend grouped by your cost allocation tag (per-project breakdown):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ce&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get-cost-and-usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-time-period&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Start=2026-02-01,End=2026-03-01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-granularity&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; DAILY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-metrics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;UnblendedCost&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-filter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&amp;quot;Dimensions&amp;quot;: {&amp;quot;Key&amp;quot;: &amp;quot;SERVICE&amp;quot;, &amp;quot;Values&amp;quot;: [&amp;quot;Amazon Bedrock&amp;quot;]}}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-group-by&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Type=TAG,Key=project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-region&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; us-east-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;: The Cost Explorer API always runs against &lt;code&gt;us-east-1&lt;&#x2F;code&gt; regardless of where your resources are deployed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cost-explorer-setup-checklist&quot;&gt;Cost Explorer Setup Checklist&lt;a class=&quot;zola-anchor&quot; href=&quot;#cost-explorer-setup-checklist&quot; aria-label=&quot;Anchor link for: cost-explorer-setup-checklist&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A few things to get right before cost data starts flowing:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The tag must be an &lt;strong&gt;active cost allocation tag&lt;&#x2F;strong&gt;. Enable it under Billing → Cost Allocation Tags.&lt;&#x2F;li&gt;
&lt;li&gt;Use the AIP ARN as the model string in LiteLLM. All invocations through it get tagged automatically.&lt;&#x2F;li&gt;
&lt;li&gt;In Cost Explorer, group by tag and select your tag key to see the per-project breakdown.&lt;&#x2F;li&gt;
&lt;li&gt;Cost data takes ~24 hours to populate after first usage, so don’t panic if it shows up empty initially.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;dependencies&quot;&gt;Dependencies&lt;a class=&quot;zola-anchor&quot; href=&quot;#dependencies&quot; aria-label=&quot;Anchor link for: dependencies&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;LiteLLM needs &lt;code&gt;boto3&lt;&#x2F;code&gt; to talk to Bedrock:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;boto3&amp;gt;=1.28.57&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make sure it’s installed in your environment, otherwise LiteLLM will fail with an import error when you try to use the &lt;code&gt;bedrock&#x2F;&lt;&#x2F;code&gt; provider.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why Plain-Text Ledger is Powerful for Gullak</title>
        <published>2026-02-02T00:00:00+00:00</published>
        <updated>2026-02-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/gullak-ledger/"/>
        <id>https://mrkaran.dev/posts/gullak-ledger/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/gullak-ledger/">&lt;p&gt;In my &lt;a href=&quot;&#x2F;posts&#x2F;gullak&#x2F;&quot;&gt;previous post&lt;&#x2F;a&gt;, I introduced Gullak, an expense tracker I built to categorize transactions using LLMs. While the initial prototype used SQLite, I’ve since made a fundamental shift in how Gullak stores data. It now uses the &lt;strong&gt;ledger-cli&lt;&#x2F;strong&gt; format—a plain-text accounting standard that has been around for over 20 years.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-core-insight&quot;&gt;The Core Insight&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-core-insight&quot; aria-label=&quot;Anchor link for: the-core-insight&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Ledger-cli uses a format that is, at its core, just text files. There are no database migrations to manage, no proprietary binary formats, and absolutely no vendor lock-in. The promise is simple: your financial data should outlive the application you use to track it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hackability-in-gullak-s-context&quot;&gt;Hackability in Gullak’s Context&lt;a class=&quot;zola-anchor&quot; href=&quot;#hackability-in-gullak-s-context&quot; aria-label=&quot;Anchor link for: hackability-in-gullak-s-context&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Moving to a plain-text format unlocked several advantages that align perfectly with modern AI capabilities and the Unix philosophy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-ai-native-format&quot;&gt;1. AI-Native Format&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-ai-native-format&quot; aria-label=&quot;Anchor link for: 1-ai-native-format&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Consider a typical transaction entry in a ledger file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2026&#x2F;01&#x2F;21 Swiggy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Expenses:Food:Delivery  584.23 INR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Liabilities:CreditCard:ICICI  -584.23 INR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This structure is trivially parseable by Large Language Models (LLMs). An AI agent can read, write, and reason about these transactions without needing complex serialization logic. Compare this to the friction of extracting data from a SQLite blob or interfacing with a proprietary API like Splitwise’s. The text &lt;em&gt;is&lt;&#x2F;em&gt; the interface.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-git-friendly&quot;&gt;2. Git-Friendly&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-git-friendly&quot; aria-label=&quot;Anchor link for: 2-git-friendly&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Because every transaction is just a few lines of text, your financial history becomes a git repository. Every change is a diff.&lt;&#x2F;p&gt;
&lt;p&gt;This gives you:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full audit trail&lt;&#x2F;strong&gt;: &lt;code&gt;git log -p -- main.ledger&lt;&#x2F;code&gt; shows exactly what changed and when.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Easy rollback&lt;&#x2F;strong&gt;: Made a mistake? &lt;code&gt;git revert&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;“What-if” scenarios&lt;&#x2F;strong&gt;: Branch off to model a major purchase or a different budget strategy.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration&lt;&#x2F;strong&gt;: Family budgeting can be handled via Pull Requests.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;3-unix-philosophy&quot;&gt;3. Unix Philosophy&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-unix-philosophy&quot; aria-label=&quot;Anchor link for: 3-unix-philosophy&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The file serves as the API. You don’t need export buttons or data liberation requests. You can use standard Unix tools to query your finances.&lt;&#x2F;p&gt;
&lt;p&gt;Find all Swiggy orders over 500 INR:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Swiggy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main.ledger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[5-9][0-9]{2,}|[0-9]{4,}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Check your monthly food spending:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ledger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main.ledger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; bal&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Expenses:Food&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;this month&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Export to CSV for Google Sheets:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ledger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main.ledger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; csv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Expenses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;4-extensibility-via-comments&quot;&gt;4. Extensibility via Comments&lt;a class=&quot;zola-anchor&quot; href=&quot;#4-extensibility-via-comments&quot; aria-label=&quot;Anchor link for: 4-extensibility-via-comments&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Gullak adds its own metadata using standard ledger comments, which are ignored by the accounting tools but used by the app:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2026&#x2F;01&#x2F;21 Zomato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ; gullak:id 7559a51f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ; gullak:source whatsapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ; gullak:user 919876543210&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Expenses:Food:Delivery  584.23 INR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gullak:id&lt;&#x2F;code&gt;: A unique ID for CRUD operations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;gullak:source&lt;&#x2F;code&gt;: Provenance tracking (e.g., entered via WhatsApp, web, or CSV).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;gullak:user&lt;&#x2F;code&gt;: Multi-user support.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Custom tags for your own organization—like &lt;code&gt;; Recurring: Netflix&lt;&#x2F;code&gt;—just work out of the box.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5-ecosystem-interoperability&quot;&gt;5. Ecosystem Interoperability&lt;a class=&quot;zola-anchor&quot; href=&quot;#5-ecosystem-interoperability&quot; aria-label=&quot;Anchor link for: 5-ecosystem-interoperability&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Because the format is standard, Gullak plays nice with others:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Paisa&lt;&#x2F;strong&gt;: Reads the same file for beautiful visualizations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;hledger&lt;&#x2F;strong&gt;: A Haskell alternative that is drop-in compatible.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Beancount&lt;&#x2F;strong&gt;: Can import ledger files.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Text Editors&lt;&#x2F;strong&gt;: Any editor (VS Code, Vim, Sublime) is a valid client.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-this-enables&quot;&gt;What This Enables&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-this-enables&quot; aria-label=&quot;Anchor link for: what-this-enables&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;&#x2F;th&gt;&lt;th&gt;How Plain Text Helps&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;WhatsApp logging&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;AI parses “swiggy 500” → appends text to file&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Receipt OCR&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Extract data → format as ledger → append&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Bank CSV import&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Transform CSV → ledger format → append&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Transaction editing&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Find by &lt;code&gt;gullak:id&lt;&#x2F;code&gt; → text replacement&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Undo&#x2F;history&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Git handles it for free&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Backup&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;cp main.ledger backup.ledger&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Migration&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;It’s text. There’s nothing to migrate.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;the-trade-off&quot;&gt;The Trade-off&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-trade-off&quot; aria-label=&quot;Anchor link for: the-trade-off&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Of course, you lose ACID transactions, database indexes, and complex SQL queries. But for personal finance, the scale makes these unnecessary trade-offs.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You likely have 10-50 transactions a month.&lt;&#x2F;li&gt;
&lt;li&gt;Running &lt;code&gt;ledger bal&lt;&#x2F;code&gt; on 10 years of data takes less than 100ms.&lt;&#x2F;li&gt;
&lt;li&gt;The simplicity &lt;em&gt;is&lt;&#x2F;em&gt; the feature.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Adopting the ledger format turns Gullak from “yet another expense app” into a thin AI layer over your permanent financial record. By decoupling the data from the application logic, we ensure that the data remains accessible, hackable, and enduring.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>CLIs are the New AI Interfaces</title>
        <published>2026-01-31T00:00:00+00:00</published>
        <updated>2026-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/plain-text-future/"/>
        <id>https://mrkaran.dev/posts/plain-text-future/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/plain-text-future/">&lt;p&gt;The industry is currently obsessed with defining standards for how Large Language Models (LLMs) should interact with software. We see a proliferation of SDKs, function calling schemas, and protocols like MCP (Model Context Protocol). They all aim to solve the same problem: bridging the gap between natural language intent and deterministic code execution.&lt;&#x2F;p&gt;
&lt;p&gt;But we might be reinventing the wheel.&lt;&#x2F;p&gt;
&lt;p&gt;The most effective tools for AI agents aren’t those wrapped in heavy “AI-native” integration layers. They are the tools that adhere to a philosophy established forty years ago: the command-line interface.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-unix-philosophy-as-an-ai-protocol&quot;&gt;The Unix Philosophy as an AI Protocol&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-unix-philosophy-as-an-ai-protocol&quot; aria-label=&quot;Anchor link for: the-unix-philosophy-as-an-ai-protocol&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An LLM’s native tongue is text. It reasons in tokens, generates strings, and parses patterns. The Unix philosophy, which emphasizes small tools, plain text interfaces, and standard streams, is accidentally the perfect protocol for AI interaction.&lt;&#x2F;p&gt;
&lt;p&gt;Consider the anatomy of a well-behaved CLI:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Discovery:&lt;&#x2F;strong&gt; &lt;code&gt;tool --help&lt;&#x2F;code&gt; explains capabilities without hallucination.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Structure:&lt;&#x2F;strong&gt; &lt;code&gt;tool --json&lt;&#x2F;code&gt; provides deterministic output for parsing.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Composition:&lt;&#x2F;strong&gt; Pipes (&lt;code&gt;|&lt;&#x2F;code&gt;) allow complex workflows to be assembled on the fly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When you give an agent access to a robust CLI, you don’t need to define 50 separate function schemas. You give it a shell and a single instruction: “Figure it out using &lt;code&gt;--help&lt;&#x2F;code&gt;.”&lt;&#x2F;p&gt;
&lt;h2 id=&quot;context-economy-lazy-vs-eager-loading&quot;&gt;Context Economy: Lazy vs. Eager Loading&lt;a class=&quot;zola-anchor&quot; href=&quot;#context-economy-lazy-vs-eager-loading&quot; aria-label=&quot;Anchor link for: context-economy-lazy-vs-eager-loading&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The current approach to agent tooling often involves dumping massive JSON schemas into the context window. Connecting to a standard MCP server might load dozens of tool definitions, involving thousands of tokens describing every possible parameter, before the user has even asked a question. This is “eager loading,” and it is expensive in terms of both latency and context window utilization.&lt;&#x2F;p&gt;
&lt;p&gt;A CLI-driven approach is “lazy loaded.”&lt;&#x2F;p&gt;
&lt;p&gt;The agent starts with zero knowledge of the tool’s internals. It burns zero tokens on schema definitions. Only when tasked with a specific goal does it invoke &lt;code&gt;man&lt;&#x2F;code&gt; or &lt;code&gt;--help&lt;&#x2F;code&gt;. It retrieves exactly the information needed to construct the command, executes it, and parses the result. This reflects the professional intuition of a senior engineer. We rarely memorize documentation. Instead, we prioritize the ability to quickly discover and apply the specific flags required for the task at hand.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;leveraging-the-skills-pattern&quot;&gt;Leveraging the Skills Pattern&lt;a class=&quot;zola-anchor&quot; href=&quot;#leveraging-the-skills-pattern&quot; aria-label=&quot;Anchor link for: leveraging-the-skills-pattern&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To bridge the gap between a raw CLI and an agent’s reasoning, we can leverage the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;platform.claude.com&#x2F;docs&#x2F;en&#x2F;agents-and-tools&#x2F;agent-skills&#x2F;overview&quot;&gt;Skills&lt;&#x2F;a&gt; pattern. This is an emerging standard for agent-based systems where capabilities are documented as self-contained units of knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of writing a Python wrapper that maps an API to a function call, you provide a Markdown file that explains when and why to use a specific CLI command. The agent uses this as a semantic index.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a snippet from a &lt;code&gt;logchef.md&lt;&#x2F;code&gt; skill:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ogchef&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;escription&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;uery application logs via LogChef CLI. Use for investigating production incidents and analyzing traffic patterns.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);font-weight: bold;&quot;&gt;##&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);font-weight: bold;&quot;&gt; Common Workflows&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; Goal&lt;&#x2F;span&gt;&lt;span&gt;           |&lt;&#x2F;span&gt;&lt;span&gt; Command Pattern&lt;&#x2F;span&gt;&lt;span&gt;       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; --------------&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span&gt; ---------------------&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; Error Analysis&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;logchef sql &amp;quot;...&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;span&gt; Live Tail&lt;&#x2F;span&gt;&lt;span&gt;      |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;logchef query &amp;#39;...&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);font-weight: bold;&quot;&gt;##&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);font-weight: bold;&quot;&gt; Example: Error Rates by Minute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;To visualize error spikes, use aggregation:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```&lt;&#x2F;span&gt;&lt;span&gt;sql&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logchef &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;sql&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;SELECT toStartOfMinute(_timestamp) as ts, count() as errors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;FROM logs.app_logs WHERE service=&amp;#39;api-gateway&amp;#39; AND level=&amp;#39;ERROR&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;GROUP BY ts ORDER BY ts DESC LIMIT 60&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;output json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;cli-ai-interfaces.png&quot; alt=&quot;LogChef skill in action&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When I ask an agent to “check for error spikes in the API gateway,” Claude identifies that this skill is relevant to the request and loads it on-demand. It sees the example, adapts the SQL query to the current context, and executes the CLI command. The Markdown file serves as a few-shot prompt, teaching the model how to use the tool effectively without rigid code constraints.&lt;&#x2F;p&gt;
&lt;p&gt;I maintain similar skill sets for AWS, Kubernetes, and Nomad. The AWS skill doesn’t wrap boto3; it simply documents useful &lt;code&gt;aws ec2&lt;&#x2F;code&gt; and &lt;code&gt;aws cloudwatch&lt;&#x2F;code&gt; commands.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-developer-experience-uv-and-single-file-clis&quot;&gt;The Developer Experience: &lt;code&gt;uv&lt;&#x2F;code&gt; and Single-File CLIs&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-developer-experience-uv-and-single-file-clis&quot; aria-label=&quot;Anchor link for: the-developer-experience-uv-and-single-file-clis&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When a CLI doesn’t exist, the barrier to creating one has never been lower. Modern Python tooling, specifically &lt;code&gt;uv&lt;&#x2F;code&gt; with its inline script metadata, allows us to treat CLIs as disposable, single-file artifacts.&lt;&#x2F;p&gt;
&lt;p&gt;I recently needed an agent to manage my Trello board. Rather than fighting with the Trello API documentation or looking for an abandoned library, I had the agent generate a CLI wrapper:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;!&#x2F;usr&#x2F;bin&#x2F;env -S uv run --script&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&#x2F; script&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; requires-python = &amp;quot;&amp;gt;=3.11&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; dependencies = [&amp;quot;typer&amp;quot;, &amp;quot;httpx&amp;quot;, &amp;quot;rich&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; typer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; httpx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; typer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Typer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; list_cards&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;list_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; format&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;table&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Fetch all cards from a specific list.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Implementation details...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This script is self-contained. It defines its own dependencies. It implements &lt;code&gt;--help&lt;&#x2F;code&gt; and &lt;code&gt;--json&lt;&#x2F;code&gt; automatically via &lt;code&gt;typer&lt;&#x2F;code&gt;. It took minutes to generate and immediately unlocked Trello capabilities for the agent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-saas-imperative&quot;&gt;The SaaS Imperative&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-saas-imperative&quot; aria-label=&quot;Anchor link for: the-saas-imperative&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The strategic takeaway for SaaS founders and platform engineers is significant. Your CLI is no longer just a developer convenience; it is your primary AI API.&lt;&#x2F;p&gt;
&lt;p&gt;We are moving past the era where a REST API and a web dashboard are sufficient. If your product lacks a terminal interface, you are locking out the growing workforce of AI agents.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Browser Automation&lt;&#x2F;strong&gt; is brittle, slow, and breaks with every UI update.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Direct API Integration&lt;&#x2F;strong&gt; puts the burden of schema management on the user.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;CLIs&lt;&#x2F;strong&gt; offer a stable, discoverable, and composable interface that agents can learn and use autonomously.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The “hobby” CLI wrappers built by enthusiasts, such as those for Notion, Jira, or Spotify, are no longer just developer conveniences. They are becoming critical infrastructure. They provide the stable, text-based interface required for agents to interact with these platforms reliably.&lt;&#x2F;p&gt;
&lt;p&gt;If you want your platform to be AI-ready, don’t just build an MCP server. Build a great CLI. Make sure it supports &lt;code&gt;--json&lt;&#x2F;code&gt;. Write good man pages. The agents will figure out the rest.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Logchef v1.0: The Journey to a Real Log Viewer</title>
        <published>2025-12-22T00:00:00+00:00</published>
        <updated>2025-12-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/logchef-v1/"/>
        <id>https://mrkaran.dev/posts/logchef-v1/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/logchef-v1/">&lt;p&gt;About eight months ago I wrote about &lt;a href=&quot;&#x2F;posts&#x2F;announcing-logchef&#x2F;&quot;&gt;Logchef&lt;&#x2F;a&gt; – a log viewer I’d been building to scratch my own itch with log exploration at work. Back then it was basically a nicer way to query ClickHouse without writing raw SQL every time. Today I’m shipping v1.0, and it’s evolved into something I didn’t quite expect.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;logchef-v1-hero.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef-v1-hero.png&quot; alt=&quot;Logchef v1.0 Log Explorer&quot; width=&quot;700&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Let me walk through the major features that made it to 1.0 and some of the engineering decisions behind them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alerting-with-alertmanager-integration&quot;&gt;Alerting with Alertmanager Integration&lt;a class=&quot;zola-anchor&quot; href=&quot;#alerting-with-alertmanager-integration&quot; aria-label=&quot;Anchor link for: alerting-with-alertmanager-integration&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In that first post, I mentioned alerting as a “roadmap” item. It always felt like the obvious next step – you find a pattern in your logs, you want to know when it happens again.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;logchef-v1-alerts.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef-v1-alerts.png&quot; alt=&quot;Alerting in Logchef&quot; width=&quot;700&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;But building it took longer than expected. My first attempt was a “rooms” system – a home-grown notification router with its own email, Slack, and webhook channels. I got it working, then stared at the code for notification deduplication, grouping, silencing, and escalation. All problems that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;alerting&#x2F;latest&#x2F;alertmanager&#x2F;&quot;&gt;Alertmanager&lt;&#x2F;a&gt; has already solved and battle-tested in production for years.&lt;&#x2F;p&gt;
&lt;p&gt;So I ripped out rooms and integrated Alertmanager instead. Now Logchef just fires alerts to Alertmanager, and you get all the routing logic – Slack, PagerDuty, email, webhooks, silencing, grouping, inhibition – without me reinventing it poorly.&lt;&#x2F;p&gt;
&lt;p&gt;The workflow is simple: write a LogchefQL or SQL query, set a threshold (e.g., “fire if count &amp;gt; 100”), pick a frequency, configure severity and labels. Logchef runs your query on schedule, evaluates the threshold, and if it triggers, fires an alert. Alert history is stored with execution logs so you can debug why something fired (or didn’t).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;logchefql-from-toy-parser-to-production-backend&quot;&gt;LogchefQL: From Toy Parser to Production Backend&lt;a class=&quot;zola-anchor&quot; href=&quot;#logchefql-from-toy-parser-to-production-backend&quot; aria-label=&quot;Anchor link for: logchefql-from-toy-parser-to-production-backend&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The query language I wrote about originally was pretty basic – just filters that compiled to SQL on the frontend. Over the months it grew into something more capable, but more importantly, I rewrote the entire parser in Go and moved it to the backend. This also opens the door for a CLI tool later – same parser, same query language, different interface.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s what LogchefQL looks like now:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;namespace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;prod&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; AND&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; level=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;error&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; message,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; trace_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The pipe operator (&lt;code&gt;|&lt;&#x2F;code&gt;) selects specific columns instead of &lt;code&gt;SELECT *&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;msg.level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ERROR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; timestamp,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; msg.request.method&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Dot notation handles nested JSON fields. If your logs have a &lt;code&gt;log_attributes&lt;&#x2F;code&gt; Map column with nested data:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;log_attributes.user.name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;john&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For keys that contain dots (common in OTEL-style logs), use quoted field syntax:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;log_attributes.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;http.status_code&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 500&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;why-move-parsing-to-the-backend&quot;&gt;Why Move Parsing to the Backend?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-move-parsing-to-the-backend&quot; aria-label=&quot;Anchor link for: why-move-parsing-to-the-backend&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The original frontend parser was TypeScript. It worked, but had problems:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inconsistency&lt;&#x2F;strong&gt;: The frontend generated SQL, but the backend had no idea what that SQL meant. Validation happened in two places.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Type-awareness&lt;&#x2F;strong&gt;: ClickHouse has &lt;code&gt;Map&lt;&#x2F;code&gt;, &lt;code&gt;JSON&lt;&#x2F;code&gt;, &lt;code&gt;LowCardinality&lt;&#x2F;code&gt;, and various string types. The frontend didn’t know the schema, so it couldn’t generate optimal SQL for each column type. For a &lt;code&gt;Map(String, String)&lt;&#x2F;code&gt; column, you want &lt;code&gt;mapContains()&lt;&#x2F;code&gt; or &lt;code&gt;[&#x27;key&#x27;]&lt;&#x2F;code&gt; access. For &lt;code&gt;JSON&lt;&#x2F;code&gt;, you want &lt;code&gt;JSONExtractString()&lt;&#x2F;code&gt;. For regular &lt;code&gt;String&lt;&#x2F;code&gt;, it’s a simple comparison.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Debugging hell&lt;&#x2F;strong&gt;: When a query failed, was it the parser? The SQL generator? ClickHouse syntax? Everything happened client-side, invisible to server logs.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The new architecture is cleaner:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Frontend&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                  Backend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; ---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; LogchefQL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; query&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                         |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Parse&lt;&#x2F;span&gt;&lt;span&gt; (Go&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                         |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Validate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; against&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; schema&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                         |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Generate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; type-aware&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; SQL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; SQL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; results&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;----&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Execute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; on&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ClickHouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The backend exposes three endpoints: &lt;code&gt;&#x2F;logchefql&#x2F;translate&lt;&#x2F;code&gt; (returns the SQL for “View as SQL”), &lt;code&gt;&#x2F;logchefql&#x2F;validate&lt;&#x2F;code&gt; (real-time validation with debouncing), and &lt;code&gt;&#x2F;logchefql&#x2F;query&lt;&#x2F;code&gt; (parse, validate, execute, return results).&lt;&#x2F;p&gt;
&lt;p&gt;Moving parsing to the backend also made the field sidebar implementation cleaner – the same schema-aware code that generates WHERE clauses can filter field values based on your current query.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-field-sidebar&quot;&gt;The Field Sidebar&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-field-sidebar&quot; aria-label=&quot;Anchor link for: the-field-sidebar&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you’ve used Kibana, you know the interaction: click a field, see its top values, click a value to add it as a filter. It’s the fastest way to explore logs when you don’t know exactly what you’re looking for.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;logchef-v1-sidebar.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef-v1-sidebar.png&quot; alt=&quot;Kibana-inspired Field Sidebar&quot; width=&quot;700&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Building this for ClickHouse required solving a few problems:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;high-cardinality-fields&quot;&gt;High-Cardinality Fields&lt;a class=&quot;zola-anchor&quot; href=&quot;#high-cardinality-fields&quot; aria-label=&quot;Anchor link for: high-cardinality-fields&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can’t just run &lt;code&gt;SELECT DISTINCT field FROM logs&lt;&#x2F;code&gt; on a table with billions of rows. String fields like &lt;code&gt;trace_id&lt;&#x2F;code&gt; would take forever and return millions of values.&lt;&#x2F;p&gt;
&lt;p&gt;The solution is a hybrid loading strategy based on column types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LowCardinality and Enum fields&lt;&#x2F;strong&gt;: Auto-load values when the sidebar opens. These are designed for fields with limited distinct values.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;String fields&lt;&#x2F;strong&gt;: Require an explicit click. A badge shows the count is unknown until you ask.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Complex types (Map, Array, Tuple, JSON)&lt;&#x2F;strong&gt;: Excluded. You can’t have meaningful “distinct values” for a JSON blob.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;progressive-loading&quot;&gt;Progressive Loading&lt;a class=&quot;zola-anchor&quot; href=&quot;#progressive-loading&quot; aria-label=&quot;Anchor link for: progressive-loading&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Each field loads in parallel (max 4 concurrent) with a 15-second timeout. One slow or failed field doesn’t block others – you get a retry button for that specific field.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;query-context&quot;&gt;Query Context&lt;a class=&quot;zola-anchor&quot; href=&quot;#query-context&quot; aria-label=&quot;Anchor link for: query-context&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The sidebar respects your current query. If you’ve filtered to &lt;code&gt;level=&quot;error&quot;&lt;&#x2F;code&gt;, the field values update to show only values from error logs. This happens through the backend – the field values endpoint accepts the current LogchefQL query and applies it as a WHERE clause filter. Same parser, same SQL generator, consistent results.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;query-cancellation&quot;&gt;Query Cancellation&lt;a class=&quot;zola-anchor&quot; href=&quot;#query-cancellation&quot; aria-label=&quot;Anchor link for: query-cancellation&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Hit Esc and it cancels the query in ClickHouse. Without this, pressing “Cancel” would just hide the spinner – the query kept running on the server, burning resources.&lt;&#x2F;p&gt;
&lt;p&gt;The implementation uses ClickHouse’s query ID feature:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; logs &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SETTINGS query_id &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;logchef-abc123&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When you hit Esc, the frontend calls a cancellation endpoint that runs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;KILL&lt;&#x2F;span&gt;&lt;span&gt; QUERY &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; query_id &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;logchef-abc123&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The original query returns an error, the UI clears, ClickHouse frees resources. Simple, but requires plumbing the query ID through every execution path.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ai-query-assistant&quot;&gt;AI Query Assistant&lt;a class=&quot;zola-anchor&quot; href=&quot;#ai-query-assistant&quot; aria-label=&quot;Anchor link for: ai-query-assistant&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;“Write a query that finds slowest endpoints by p99” actually works. The AI generates LogchefQL or SQL based on natural language and your table schema.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;logchef-v1-ai.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef-v1-ai.png&quot; alt=&quot;AI Query Assistant&quot; width=&quot;700&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Under the hood it uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sashabaranov&#x2F;go-openai&quot;&gt;go-openai&lt;&#x2F;a&gt;, so any OpenAI-compatible endpoint works – OpenAI, Ollama, vLLM, whatever you prefer. The system prompt includes your table schema so the model knows what fields exist.&lt;&#x2F;p&gt;
&lt;p&gt;There’s also an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;logchef-mcp&quot;&gt;MCP server&lt;&#x2F;a&gt; that exposes Logchef to AI assistants like Claude Desktop, Cursor, or any MCP-compatible client. Instead of context-switching between your AI chat and the log viewer, you can ask directly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;“What log sources do I have access to?”&lt;&#x2F;li&gt;
&lt;li&gt;“Find all 500 errors in the last hour from the web service”&lt;&#x2F;li&gt;
&lt;li&gt;“Show me a histogram of log volume over the past day”&lt;&#x2F;li&gt;
&lt;li&gt;“What are the most common error messages in the database logs?”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The MCP server handles discovery (teams, sources, schemas), querying (full ClickHouse SQL), analysis (histograms, saved queries), and even admin operations. It’s a separate binary that runs alongside Logchef – configure it once, and your AI assistant can query your logs through natural conversation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compact-view-for-terminal-lovers&quot;&gt;Compact View for Terminal Lovers&lt;a class=&quot;zola-anchor&quot; href=&quot;#compact-view-for-terminal-lovers&quot; aria-label=&quot;Anchor link for: compact-view-for-terminal-lovers&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;logchef-v1-compact.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef-v1-compact.png&quot; alt=&quot;Compact Terminal-Style Log View&quot; width=&quot;700&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Not everyone wants a table. The compact view is a terminal-style display that shows logs as formatted text with syntax highlighting. Denser and faster to scan for certain debugging workflows.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;query-variables&quot;&gt;Query Variables&lt;a class=&quot;zola-anchor&quot; href=&quot;#query-variables&quot; aria-label=&quot;Anchor link for: query-variables&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Use &lt;code&gt;{{namespace}}&lt;&#x2F;code&gt; in your query, and an input field appears automatically. Great for saved queries that teams want to reuse with different parameters.&lt;&#x2F;p&gt;
&lt;p&gt;This was a community contribution from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;songxuanqing&quot;&gt;@songxuanqing&lt;&#x2F;a&gt;. The implementation detects &lt;code&gt;{{variable}}&lt;&#x2F;code&gt; patterns in the query text and renders input fields dynamically.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;team-management-and-rbac&quot;&gt;Team Management and RBAC&lt;a class=&quot;zola-anchor&quot; href=&quot;#team-management-and-rbac&quot; aria-label=&quot;Anchor link for: team-management-and-rbac&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;logchef-v1-teams.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef-v1-teams.png&quot; alt=&quot;Team Management and RBAC&quot; width=&quot;700&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Logchef supports multi-tenancy with role-based access. Teams can have multiple data sources, and users can be members of multiple teams with different roles:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Admin&lt;&#x2F;strong&gt;: Full access, can manage team members and sources&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Editor&lt;&#x2F;strong&gt;: Can create&#x2F;edit saved queries and collections&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Viewer&lt;&#x2F;strong&gt;: Read-only access to query and explore logs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This integrates with OIDC for SSO, so you can use your existing identity provider.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;admin-ui-for-runtime-config&quot;&gt;Admin UI for Runtime Config&lt;a class=&quot;zola-anchor&quot; href=&quot;#admin-ui-for-runtime-config&quot; aria-label=&quot;Anchor link for: admin-ui-for-runtime-config&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Configure stuff without touching config files. The admin settings panel lets you change AI configuration, Alertmanager connection, authentication settings, and query timeouts.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;logchef-v1-settings.gif&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef-v1-settings.gif&quot; alt=&quot;Admin Settings UI&quot; width=&quot;700&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was a migration from config files to database-backed settings. On first boot, Logchef seeds the database from &lt;code&gt;config.toml&lt;&#x2F;code&gt;. After that, the UI takes over and changes are stored in SQLite. Backward compatible – existing config files still work, the UI just overrides them at runtime. No more SSH-ing into production to bump a timeout.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prometheus-metrics&quot;&gt;Prometheus Metrics&lt;a class=&quot;zola-anchor&quot; href=&quot;#prometheus-metrics&quot; aria-label=&quot;Anchor link for: prometheus-metrics&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A &lt;code&gt;&#x2F;metrics&lt;&#x2F;code&gt; endpoint exposes query execution times, error rates, active queries, and other operational data. There’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;logchef&#x2F;tree&#x2F;main&#x2F;dashboards&quot;&gt;pre-built Grafana dashboard&lt;&#x2F;a&gt; for monitoring Logchef itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-not-in-1-0&quot;&gt;What’s Not in 1.0&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-not-in-1-0&quot; aria-label=&quot;Anchor link for: what-s-not-in-1-0&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Some things didn’t make the cut:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Live tail&lt;&#x2F;strong&gt;: Streaming logs in real-time. Still on the roadmap.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Dashboarding&lt;&#x2F;strong&gt;: Multiple visualizations on one page. Logchef is query-focused; for dashboards, you probably want Grafana with ClickHouse as a datasource.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;calling-it-1-0&quot;&gt;Calling It 1.0&lt;a class=&quot;zola-anchor&quot; href=&quot;#calling-it-1-0&quot; aria-label=&quot;Anchor link for: calling-it-1-0&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Calling something “1.0” is weird. There’s no clear line where software becomes “ready.” But I’ve been using Logchef daily at work for months now, and it’s at the point where I trust it. The rough edges are mostly smoothed out. The architecture feels right.&lt;&#x2F;p&gt;
&lt;p&gt;Building tools you use yourself is different. You’re the first to hit the rough edges, so you fix them. Slower than building for imaginary users, but the result is something you actually want to use.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks again to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nadh.in&#x2F;&quot;&gt;Kailash&lt;&#x2F;a&gt; for the early direction (schema-agnostic was his idea), and to everyone at Zerodha who’s been using this and giving feedback. Thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;songxuanqing&quot;&gt;@songxuanqing&lt;&#x2F;a&gt; for query variables and other contributors for docs and bug fixes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;demo.logchef.app&quot;&gt;Demo&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logchef.app&quot;&gt;Docs&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;logchef&quot;&gt;GitHub&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;logchef&#x2F;releases&#x2F;tag&#x2F;v1.0.0&quot;&gt;v1.0.0 Release&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Fixing a CIBIL Score Disaster with AI</title>
        <published>2025-12-04T00:00:00+00:00</published>
        <updated>2025-12-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/fixing-cibil-with-ai/"/>
        <id>https://mrkaran.dev/posts/fixing-cibil-with-ai/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/fixing-cibil-with-ai/">&lt;p&gt;About a month ago, I downloaded my CIBIL report expecting a routine check. Instead, I found loans from lenders I had never interacted with, written-off accounts, overdues from fintechs I had never installed, and even two-wheeler loan enquiries. I don’t even ride a bike.&lt;&#x2F;p&gt;
&lt;p&gt;My credit score had collapsed to under 680. I stared at the report trying to understand how this could happen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-root-cause-a-wrong-date-of-birth&quot;&gt;The Root Cause: A Wrong Date of Birth&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-root-cause-a-wrong-date-of-birth&quot; aria-label=&quot;Anchor link for: the-root-cause-a-wrong-date-of-birth&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Buried in my profile section was the problem: my date of birth was wrong. Not a typo, but a completely different year.&lt;&#x2F;p&gt;
&lt;p&gt;Because of this mismatch, CIBIL’s system had paired my PAN and mobile number with someone else’s DOB, effectively merging two individuals’ credit histories into one report. The accounts mapped to me included:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Aditya Birla Capital&lt;&#x2F;strong&gt;: Short-term personal loan marked as doubtful&#x2F;substandard&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Clix Capital&lt;&#x2F;strong&gt;: A loan marked written-off (₹50,000+)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Poonawalla Fincorp&lt;&#x2F;strong&gt;: Personal loans with delayed payments&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ring &#x2F; Kissht&lt;&#x2F;strong&gt;: Unsecured digital loans&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;InCred&lt;&#x2F;strong&gt;: Personal loan I never took&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Dhani Loans&lt;&#x2F;strong&gt;: BNPL-style loan with unrecognized activity&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Axio (Capital Float)&lt;&#x2F;strong&gt;: Old consumer loan&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;KrazyBee&lt;&#x2F;strong&gt;: Various short-term loans&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Transactree&lt;&#x2F;strong&gt;: Small-ticket personal loan&lt;&#x2F;li&gt;
&lt;li&gt;Multiple enquiries from HDFC, ICICI, IDFC First, Shriram Finance, and others&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some were written-off, others 90+ days overdue, others still active. On paper, I looked like a serial defaulter.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-ai-to-understand-the-problem&quot;&gt;Using AI to Understand the Problem&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-ai-to-understand-the-problem&quot; aria-label=&quot;Anchor link for: using-ai-to-understand-the-problem&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I opened ChatGPT and uploaded the entire PDF with a simple prompt: identify everything wrong in this report.&lt;&#x2F;p&gt;
&lt;p&gt;Within minutes, it had mapped every suspicious account, flagged which ones didn’t match my history, highlighted the incorrect DOB, and explained why CIBIL systems mis-map accounts when demographic data is inconsistent.&lt;&#x2F;p&gt;
&lt;p&gt;More usefully, it drafted formal dispute letters citing relevant RBI regulations and prepared lender-specific escalations with the right legal language. It felt like having a credit compliance team on demand.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-dispute-process&quot;&gt;The Dispute Process&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-dispute-process&quot; aria-label=&quot;Anchor link for: the-dispute-process&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;With the AI-drafted communications as a starting point, I sent disputes to CIBIL and direct emails to each lender. The key was being specific: every email included the CIBIL report control number, the exact account identifiers from the report, and references to specific RBI regulations.&lt;&#x2F;p&gt;
&lt;p&gt;For example, when writing to Poonawalla Fincorp about a co-lending arrangement with Kissht, the email included:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CIBIL Report details:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Control Number: [REDACTED]&lt;&#x2F;li&gt;
&lt;li&gt;Downloaded on: [DATE]&lt;&#x2F;li&gt;
&lt;li&gt;Where your name appears: “POONAFIN – Personal Loan – Account No. [REDACTED]”&lt;&#x2F;li&gt;
&lt;li&gt;Delinquency trail in history: DPD values 35 &#x2F; 62 &#x2F; 93 &#x2F; 124 during [MONTHS]&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I reiterate that I have never applied for, signed, or availed any facility from Poonawalla&#x2F;Kissht. This appears to be erroneous mapping &#x2F; data contamination.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The emails also cited the relevant regulations explicitly:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Under Section 45-A(2) of the Credit Information Companies (Regulation) Act 2005 and Para 7.2.2 &amp;amp; 8.1.3 of the RBI Master Directions on Credit Information Companies (2021), please verify this record against your origination&#x2F;KYC systems. If the record is not verifiable or was created with misused&#x2F;incorrect KYC, immediately instruct TransUnion CIBIL to delete&#x2F;correct the entry.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This kind of precise, regulation-backed language gets results. Vague complaints are likely to get ignored or deprioritized. Specific complaints with control numbers, account IDs, and regulatory citations get escalated to teams that can actually fix things.&lt;&#x2F;p&gt;
&lt;p&gt;For co-lending cases (common with fintechs like Kissht, Ring, etc.), I learned to CC both parties and explicitly request a “consolidated correction” so the entry gets fully removed rather than bouncing between two institutions.&lt;&#x2F;p&gt;
&lt;p&gt;When initial responses were slow, I sent reminders that referenced the original complaint number and the 30-day statutory deadline:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a reminder regarding my complaint Ref No. [REDACTED]. The acknowledgement stated that the issue would be resolved by [DATE], yet I have not received any confirmation.&lt;&#x2F;p&gt;
&lt;p&gt;Failure to resolve within the statutory period will leave me with no option but to escalate to the RBI Integrated Ombudsman.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;CIBIL started closing disputes. One by one, accounts were removed. Eight fraudulent accounts were purged in the first wave.&lt;&#x2F;p&gt;
&lt;p&gt;But there was a catch: even after the fraudulent accounts were removed, my DOB was still wrong. CIBIL kept closing my DOB correction disputes without actually fixing the underlying data. Their responses were templated and generic, treating it like a lender issue when DOB is actually a CIBIL demographic field that they control directly.&lt;&#x2F;p&gt;
&lt;p&gt;This required escalating to the Nodal Officer with a sharper tone:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;My Date of Birth correction dispute has been closed twice, yet my DOB remains incorrect in every new CIBIL report. This is a CIBIL demographic field — it is not lender-controlled and should have been corrected immediately once KYC was submitted.&lt;&#x2F;p&gt;
&lt;p&gt;Because of this incorrect DOB, my profile was wrongly merged with another individual’s data. Although many wrong accounts have been removed, the root cause remains uncorrected — the wrong DOB is still mapped, and therefore the risk of future wrongful linkages still exists.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Only after escalating to the Nodal Officer did the DOB finally get corrected. Once that happened, the system stopped associating the other person’s accounts with my profile. It was an algorithmic identity collision, and fixing the DOB resolved it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-outcome&quot;&gt;The Outcome&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-outcome&quot; aria-label=&quot;Anchor link for: the-outcome&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My latest CIBIL report shows the correct date of birth, zero fraudulent loans, no written-off or overdue accounts, and a score back in a healthy range. Only my actual accounts remain.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-learned&quot;&gt;What I Learned&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-learned&quot; aria-label=&quot;Anchor link for: what-i-learned&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Credit bureaus are not infallible. A single incorrect demographic detail (in my case, a mismatched DOB) can cause wrong loan mappings, score drops, false delinquencies, and a complete distortion of your financial identity.&lt;&#x2F;p&gt;
&lt;p&gt;The resolution required documentation, persistence with escalations, and an understanding of RBI regulations. AI made the last part significantly easier. Instead of spending hours researching dispute procedures and drafting formal letters, I could focus on gathering the right documents and following up with the right people.&lt;&#x2F;p&gt;
&lt;p&gt;If you haven’t checked your CIBIL report recently, it’s worth verifying that your basic details are correct: DOB, PAN, address, mobile, email. One wrong field can create problems that take weeks to untangle.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AI and Home-Cooked Software</title>
        <published>2025-10-05T00:00:00+00:00</published>
        <updated>2025-10-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/ai-home-cooked-software/"/>
        <id>https://mrkaran.dev/posts/ai-home-cooked-software/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/ai-home-cooked-software/">&lt;p&gt;Everyone is worried that AI will replace programmers. They’re missing the real revolution: AI is turning everyone into one.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been noticing a new pattern: people with deep domain knowledge but no coding experience are now building their own tools. Armed with AI assistants, they can create custom workflows in a matter of days, bypassing traditional development cycles. Are these solutions production-ready? Not even close. But they solve urgent, specific problems, and that’s what matters. Tasks that once required weeks of specialized training are quickly becoming weekend projects.&lt;&#x2F;p&gt;
&lt;p&gt;This trend is happening even within the AI companies themselves. Anthropic, for example, shared how their own teams use Claude to accelerate their work. Crucially, this isn’t limited to developers. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;news&#x2F;how-anthropic-teams-use-claude-code&quot;&gt;Their post details how non-technical staff now build their own solutions&lt;&#x2F;a&gt; and create custom automations, providing a powerful real-world example of this new paradigm.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;home-cooked-software&quot;&gt;Home-Cooked Software&lt;a class=&quot;zola-anchor&quot; href=&quot;#home-cooked-software&quot; aria-label=&quot;Anchor link for: home-cooked-software&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Why search for a generic tool when you can build exactly what you need? This question leads to what I call ‘home-cooked software’: small, personal applications we build for ourselves, tailored to our specific needs. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.robinsloan.com&#x2F;notes&#x2F;home-cooked-app&#x2F;&quot;&gt;Robin Sloan&lt;&#x2F;a&gt; beautifully describes building an app as making “a home-cooked meal,” while &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;maggieappleton.com&#x2F;home-cooked-software&#x2F;&quot;&gt;Maggie Appleton&lt;&#x2F;a&gt; writes about “barefoot developers” creating software outside traditional industry structures.&lt;&#x2F;p&gt;
&lt;p&gt;What’s new isn’t the concept but the speed and accessibility. With AI, a custom export format, a specific workflow, or the perfect integration is now an afternoon’s work. We’re entering an unprecedented era where the barrier between wanting a tool and having it has nearly vanished.&lt;&#x2F;p&gt;
&lt;p&gt;But let’s be clear: the journey from a prototype to a production-ready application is as challenging as ever. In my experience, an AI can churn out a first draft in a few hours, which gets you surprisingly far. But the devil is in the details, and the last stretch of the journey – handling edge cases, ensuring security, and debugging subtle issues – can stretch into weeks. This distinction is crucial. AI isn’t replacing programmers; it’s creating millions of people who can build simple tools. There’s a significant difference.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-new-economics&quot;&gt;The New Economics&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-new-economics&quot; aria-label=&quot;Anchor link for: the-new-economics&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;AI is fundamentally reshaping the economics of building software. Before AI, even a simple tool required a significant time investment in learning programming basics, understanding frameworks, and debugging. Only tools with broad appeal or critical importance justified the effort. Now, that effort is measured in hours, not months, and the primary barrier is no longer technical knowledge, but imagination and a clear understanding of one’s own needs.&lt;&#x2F;p&gt;
&lt;p&gt;This doesn’t apply to complex or security-critical systems, where deep expertise remains essential. But for the long tail of personal utilities, automation scripts, and custom workflows, the math has changed completely. I’m talking about solving all those minor irritations that pile up: the script to reformat a specific CSV export, the dashboard showing exactly the three metrics you care about, or a script that pulls data from a personal project management tool to sync with an obscure time-tracking app.&lt;&#x2F;p&gt;
&lt;p&gt;These tools might be held together with digital duct tape, but they solve real problems for real people. And increasingly, that’s all that matters.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-hidden-costs&quot;&gt;The Hidden Costs&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-hidden-costs&quot; aria-label=&quot;Anchor link for: the-hidden-costs&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;But this newfound capability isn’t free. It comes with what I call the “AI Tax”: a set of hidden costs that are rarely discussed.&lt;&#x2F;p&gt;
&lt;p&gt;First, prompt engineering can be surprisingly time-consuming, especially for tasks of moderate complexity. While simple requests are often straightforward, anything more nuanced can become an iterative dialogue. You prompt, the AI generates a flawed output, you clarify the requirements, and it returns a new version that misses a different detail. It’s a classic 80&#x2F;20 scenario: you get 80% of the way there with a simple prompt, but achieving the final 20% of correctness requires a disproportionate amount of effort in refining, correcting, and clarifying your intent to the model.&lt;&#x2F;p&gt;
&lt;p&gt;Second, there’s the verification burden. Every line of AI-generated code is a plausible-looking liability. It may pass basic tests, only to fail spectacularly in production with an edge case you never considered. AI learned from the public internet, which means it absorbed all the bad code along with the good. SQL injection vulnerabilities, hardcoded secrets, race conditions—an AI will happily generate them all with complete confidence.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps the most frustrating aspect is “hallucination debugging”: the uniquely modern challenge of troubleshooting plausible-looking code that relies on APIs or methods that simply don’t exist. Your codebase becomes a patchwork of different AI-generated styles and patterns. Six months later, it’s an archaeological exercise to determine which parts you wrote and which parts an AI contributed.&lt;&#x2F;p&gt;
&lt;p&gt;But the most significant danger is that AI enables you to build systems you don’t fundamentally understand. When that system inevitably breaks, you lack the foundational knowledge to debug it effectively.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-for-one&quot;&gt;Building for One&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-for-one&quot; aria-label=&quot;Anchor link for: building-for-one&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Despite these challenges, there’s something profoundly liberating about building software just for yourself. Instead of just sketching out ideas, I’ve started building these small, specific tools. For this blog, I wanted a simple lightbox for images; instead of pulling in a heavy external library, I had Claude write a 50-line JavaScript snippet that did exactly what I needed. I built a simple, single-page &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cagr.mrkaran.dev&quot;&gt;compound interest calculator&lt;&#x2F;a&gt; tailored for my own financial planning. To save myself from boilerplate at work, I created &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;prom2grafana.mrkaran.dev&quot;&gt;prom2grafana&lt;&#x2F;a&gt;, a tool that uses an LLM to convert Prometheus metrics into Grafana dashboards.&lt;&#x2F;p&gt;
&lt;p&gt;Ten years ago, I might have thought about generalizing these tools, making them useful for others, perhaps even starting an open source project. Today? I just want a tool that works exactly how I think. I don’t need to handle anyone else’s edge cases or preferences. Home-cooked software doesn’t need product-market fit—it just needs to fit you.&lt;&#x2F;p&gt;
&lt;p&gt;We’re witnessing the emergence of a new software layer. At the base are the professionally-built, robust systems that power our world: databases, operating systems, and rock-solid frameworks. In the middle are commercial applications built for broad audiences. And at the top, a new layer is forming: millions of tiny, personal tools that solve individual problems in highly specific ways.&lt;&#x2F;p&gt;
&lt;p&gt;This top layer is messy, fragile, and often incomprehensible to anyone but its creator. It’s also incredibly empowering. Creating simple software is becoming as accessible as writing. And just as most writing isn’t professional literature, most of this new software won’t be professional-grade. That’s not just okay; it’s the point.&lt;&#x2F;p&gt;
&lt;p&gt;The implications are profound. Subject-matter experts can now solve their own problems without waiting for engineering resources, and tools can be hyper-personalized to a degree that is impossible for commercial software. This unlocks a wave of creativity, completely unconstrained by the need to generalize or find a market.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, there are legitimate concerns. Security is a real risk, though the profile changes when a tool runs locally on personal data with no external access. We’re creating personal technical debt, but when a personal tool breaks, the owner is the only one affected. They can choose to fix it, rebuild it, or abandon it without impacting anyone else. Organizations, on the other hand, will soon have to grapple with the proliferation of incompatible personal tools and establish new patterns for managing them.&lt;&#x2F;p&gt;
&lt;p&gt;But these challenges pale in comparison to the opportunities. The barrier between user and creator is dissolving. We’re entering the age of home-cooked software, where building your own tool is becoming as natural as cooking your own meal.&lt;&#x2F;p&gt;
&lt;p&gt;The kitchen is open. What will you cook?&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>State of My Homelab 2025</title>
        <published>2025-10-04T00:00:00+00:00</published>
        <updated>2025-10-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/state-homelab-2025/"/>
        <id>https://mrkaran.dev/posts/state-homelab-2025/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/state-homelab-2025/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;a class=&quot;zola-anchor&quot; href=&quot;#introduction&quot; aria-label=&quot;Anchor link for: introduction&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For the past five years, I have maintained a homelab in various configurations. This journey has served as a practical exploration of different technologies, from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;home-server-setup&#x2F;&quot;&gt;Raspberry Pi clusters running K3s&lt;&#x2F;a&gt; to a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;home-server-updates&#x2F;&quot;&gt;hybrid cloud setup&lt;&#x2F;a&gt; and eventually a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;home-server-nomad&#x2F;&quot;&gt;cloud-based Nomad setup&lt;&#x2F;a&gt;. Each iteration provided valuable lessons, consistently highlighting the operational benefits of simplicity.&lt;&#x2F;p&gt;
&lt;p&gt;This article details the current state of my homelab. A primary motivation for this build was to dip my toes into “actual” homelabbing—that is, maintaining a physical server at home. The main design goal was to build a dedicated, reliable, and performant server that is easy to maintain. This led me to move away from complex container orchestrators like Kubernetes in favor of a more straightforward Docker Compose workflow. I will cover the hardware build, software architecture, and the rationale behind the key decisions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardware-configuration&quot;&gt;Hardware Configuration&lt;a class=&quot;zola-anchor&quot; href=&quot;#hardware-configuration&quot; aria-label=&quot;Anchor link for: hardware-configuration&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After considerable research, I selected components to balance performance, power efficiency, and cost. The server is designed for 24&#x2F;7 operation in a home environment, making noise and power consumption important considerations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-build&quot;&gt;The Build&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-build&quot; aria-label=&quot;Anchor link for: the-build&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Component&lt;&#x2F;th&gt;&lt;th&gt;Choice&lt;&#x2F;th&gt;&lt;th&gt;Price&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CPU&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;AMD Ryzen 5 7600X (6-core, 4.7 GHz)&lt;&#x2F;td&gt;&lt;td&gt;$167.58&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CPU Cooler&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;ARCTIC Liquid Freezer III Pro 360&lt;&#x2F;td&gt;&lt;td&gt;$89.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Motherboard&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;MSI B650M Gaming Plus WiFi&lt;&#x2F;td&gt;&lt;td&gt;$225.83&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;RAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Kingston FURY Beast 32GB DDR5-6000&lt;&#x2F;td&gt;&lt;td&gt;$136.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Boot Drive&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;WD Blue SN580 500GB NVMe&lt;&#x2F;td&gt;&lt;td&gt;$88.76&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Storage 1&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;WD Red Plus 4TB (5400 RPM)&lt;&#x2F;td&gt;&lt;td&gt;$99.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Storage 2&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Seagate IronWolf Pro 4TB (7200 RPM)&lt;&#x2F;td&gt;&lt;td&gt;$150.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Case&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;ASUS Prime AP201 MicroATX&lt;&#x2F;td&gt;&lt;td&gt;$89.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;PSU&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Corsair SF750 (80+ Platinum)&lt;&#x2F;td&gt;&lt;td&gt;$169.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Total&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;$1,219.12&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;div class=&quot;image-grid&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;homelab_2025_1_opt.jpg&quot; class=&quot;lightbox-thumbnail&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab_2025_1_opt.jpg&quot; alt=&quot;Homelab build in progress&quot;&gt;&lt;&#x2F;a&gt;
&lt;a href=&quot;&#x2F;images&#x2F;homelab_2025_2_opt.jpg&quot; class=&quot;lightbox-thumbnail&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab_2025_2_opt.jpg&quot; alt=&quot;Completed build with RGB and storage drives&quot;&gt;&lt;&#x2F;a&gt;
&lt;a href=&quot;&#x2F;images&#x2F;homelab_2025_3_opt.jpeg&quot; class=&quot;lightbox-thumbnail&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab_2025_3_opt.jpeg&quot; alt=&quot;MSI BIOS showing system information&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;component-rationale&quot;&gt;Component Rationale&lt;a class=&quot;zola-anchor&quot; href=&quot;#component-rationale&quot; aria-label=&quot;Anchor link for: component-rationale&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CPU&lt;&#x2F;strong&gt;: The Ryzen 5 7600X provides a strong price-to-performance ratio. Its 6 cores offer ample headroom for concurrent containerized workloads and future experimentation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Storage&lt;&#x2F;strong&gt;: The boot drive is a 500GB NVMe for fast OS and application performance. The primary storage consists of two 4TB HDDs in a &lt;strong&gt;BTRFS RAID 1&lt;&#x2F;strong&gt; configuration. To mitigate the risk of correlated failures, I chose drives from different manufacturers (WD and Seagate) purchased at different times.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RAM&lt;&#x2F;strong&gt;: 32GB of DDR5-6000 provides sufficient memory for a growing number of services without risking contention.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Case &amp;amp; PSU&lt;&#x2F;strong&gt;: The ASUS Prime AP201 is a compact MicroATX case with a clean aesthetic suitable for a home office. The Corsair SF750 (80+ Platinum) PSU was chosen for its efficiency and to provide capacity for a future GPU for local LLM or transcoding workloads.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;system-architecture-deployment&quot;&gt;System Architecture &amp;amp; Deployment&lt;a class=&quot;zola-anchor&quot; href=&quot;#system-architecture-deployment&quot; aria-label=&quot;Anchor link for: system-architecture-deployment&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My previous setups involved Kubernetes and Nomad, but the operational overhead proved unnecessary for my use case. I have since standardized on a Git-based, Docker Compose workflow that prioritizes simplicity and transparency.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;directory-structure-and-stacks&quot;&gt;Directory Structure and “Stacks”&lt;a class=&quot;zola-anchor&quot; href=&quot;#directory-structure-and-stacks&quot; aria-label=&quot;Anchor link for: directory-structure-and-stacks&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The core of the system is a Git repository that holds all configurations. Each service is defined as a self-contained “stack” in its own directory. The structure is organized by machine, making it easy to manage multiple environments:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;homelab&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; deploy.sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;                 #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Main deployment script&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; justfile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;                  #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Task runner for common commands&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;└──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; machines&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; floyd-homelab-1&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Primary home server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; config.sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;         #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; SSH and deployment settings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stacks&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; immich&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       │&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker-compose.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; paperless&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;           └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker-compose.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; floyd-pub-1&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;          #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Public-facing VPS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; config.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stacks&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;            ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; caddy&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;            └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ntfy&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This modular approach allows me to manage each application’s configuration, including its &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; and any related files, as an independent unit.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deployment-workflow&quot;&gt;Deployment Workflow&lt;a class=&quot;zola-anchor&quot; href=&quot;#deployment-workflow&quot; aria-label=&quot;Anchor link for: deployment-workflow&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Deployments are handled by a custom &lt;code&gt;deploy.sh&lt;&#x2F;code&gt; script, with a &lt;code&gt;justfile&lt;&#x2F;code&gt; providing a convenient command-runner interface. The process is fundamentally simple:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sync&lt;&#x2F;strong&gt;: &lt;code&gt;rsync&lt;&#x2F;code&gt; copies the specified stack’s directory from the local Git repository to a &lt;code&gt;REMOTE_BASE_PATH&lt;&#x2F;code&gt; (e.g., &lt;code&gt;&#x2F;opt&#x2F;homelab&lt;&#x2F;code&gt;) on the target machine.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Execute&lt;&#x2F;strong&gt;: &lt;code&gt;ssh&lt;&#x2F;code&gt; runs the appropriate &lt;code&gt;docker compose&lt;&#x2F;code&gt; command on the remote machine.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Each machine’s connection settings (&lt;code&gt;SSH_HOST&lt;&#x2F;code&gt;, &lt;code&gt;SSH_USER&lt;&#x2F;code&gt;, &lt;code&gt;REMOTE_BASE_PATH&lt;&#x2F;code&gt;) are defined in its &lt;code&gt;machines&#x2F;&amp;lt;name&amp;gt;&#x2F;config.sh&lt;&#x2F;code&gt; file. This file can also contain &lt;code&gt;pre_deploy&lt;&#x2F;code&gt; and &lt;code&gt;post_deploy&lt;&#x2F;code&gt; hooks for custom actions.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;justfile&lt;&#x2F;code&gt; makes daily operations trivial:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Deploy a single stack to a machine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;just&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; deploy-stack&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; floyd-homelab-1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; immich&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; View the logs for a stack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;just&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; floyd-homelab-1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; immich&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Test a deployment without making changes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;just&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dry-run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; floyd-homelab-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab-deploy.gif&quot; alt=&quot;Deployment workflow demonstration&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This system provides fine-grained control over deployments, with support for actions like &lt;code&gt;up&lt;&#x2F;code&gt;, &lt;code&gt;down&lt;&#x2F;code&gt;, &lt;code&gt;restart&lt;&#x2F;code&gt;, &lt;code&gt;pull&lt;&#x2F;code&gt;, and &lt;code&gt;recreate&lt;&#x2F;code&gt; (which also removes persistent volumes).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;container-configuration-patterns&quot;&gt;Container &amp;amp; Configuration Patterns&lt;a class=&quot;zola-anchor&quot; href=&quot;#container-configuration-patterns&quot; aria-label=&quot;Anchor link for: container-configuration-patterns&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;To keep the system consistent, I follow a few key patterns:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data Persistence&lt;&#x2F;strong&gt;: Instead of using Docker named volumes, I use host bind mounts. All persistent data for a service is stored in a dedicated directory on the host, typically &lt;code&gt;&#x2F;data&#x2F;&amp;lt;service-name&amp;gt;&lt;&#x2F;code&gt;. This makes backups and data management more transparent.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Reverse Proxy Network&lt;&#x2F;strong&gt;: The Caddy stack defines a shared Docker network called &lt;code&gt;public_proxy&lt;&#x2F;code&gt;. Other stacks that need to be exposed to the internet are configured to join this network. This allows Caddy to discover and proxy them without exposing their ports on the host machine. I have written about this pattern in detail in a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;exposing-services&#x2F;&quot;&gt;previous post&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Port Exposure&lt;&#x2F;strong&gt;: Services behind the reverse proxy use the &lt;code&gt;expose&lt;&#x2F;code&gt; directive in their &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; to make ports available to Caddy within the Docker network. I avoid binding ports directly with &lt;code&gt;ports&lt;&#x2F;code&gt; unless absolutely necessary.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;multi-machine-topology&quot;&gt;Multi-Machine Topology&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-machine-topology&quot; aria-label=&quot;Anchor link for: multi-machine-topology&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The homelab comprises three distinct machines to provide isolation and redundancy.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;floyd-homelab-1 (Primary Server)&lt;&#x2F;strong&gt;: The core of the homelab, running on the AMD hardware detailed above. It runs data-intensive personal services (e.g., Immich, Paperless-ngx) and is accessible only via the Tailscale network.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;floyd-pub-1 (Public VPS)&lt;&#x2F;strong&gt;: A small cloud VPS that hosts public-facing services requiring high availability, such as DNS utilities, analytics, and notification relays.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;floyd-monitor-public (Monitoring VPS)&lt;&#x2F;strong&gt;: A small Hetzner VM running Gatus for health checks. Its independence ensures that I am alerted if the primary homelab or home network goes offline.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This distributed setup isolates my home network from the public internet and ensures that critical public services remain online even if the home server is down for maintenance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hosted-services&quot;&gt;Hosted Services&lt;a class=&quot;zola-anchor&quot; href=&quot;#hosted-services&quot; aria-label=&quot;Anchor link for: hosted-services&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The following is a breakdown of the services, or “stacks,” running on each machine. A few key services that are central to the homelab are detailed further in the next section.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;floyd-homelab-1-primary-server&quot;&gt;floyd-homelab-1 (Primary Server)&lt;a class=&quot;zola-anchor&quot; href=&quot;#floyd-homelab-1-primary-server&quot; aria-label=&quot;Anchor link for: floyd-homelab-1-primary-server&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actualbudget&#x2F;actual-server&quot;&gt;Actual&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A local-first personal finance and budgeting tool.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A powerful, enterprise-ready, open source web server with automatic HTTPS.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitea.io&#x2F;&quot;&gt;Gitea&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A Git service for personal projects.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;glanceapp&#x2F;glance&quot;&gt;Glance&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A dashboard for viewing all my feeds and data in one place.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;immich.app&#x2F;&quot;&gt;Immich&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A photo and video backup solution, directly from my mobile phone.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;karakeep.app&#x2F;&quot;&gt;Karakeep&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: An app for bookmarking everything, with AI-based tagging and full-text search.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;owntracks.org&#x2F;&quot;&gt;Owntracks&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A private location tracker for recording my own location data.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;paperless-ngx&#x2F;paperless-ngx&quot;&gt;Paperless-ngx&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A document management system that transforms physical documents into a searchable online archive.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;silverbullet.md&#x2F;&quot;&gt;Silverbullet&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A Markdown-based knowledge management and note-taking tool.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;floyd-monitor-public-monitoring-vps&quot;&gt;floyd-monitor-public (Monitoring VPS)&lt;a class=&quot;zola-anchor&quot; href=&quot;#floyd-monitor-public-monitoring-vps&quot; aria-label=&quot;Anchor link for: floyd-monitor-public-monitoring-vps&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Reverse proxy for the services on this node.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;floyd-pub-1-public-vps&quot;&gt;floyd-pub-1 (Public VPS)&lt;a class=&quot;zola-anchor&quot; href=&quot;#floyd-pub-1-public-vps&quot; aria-label=&quot;Anchor link for: floyd-pub-1-public-vps&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;beszel.dev&#x2F;&quot;&gt;Beszel-agent&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: The agent for the Beszel monitoring platform.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Reverse proxy for the services on this node.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;cloak&quot;&gt;Cloak&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A service to securely share sensitive text with others.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doggo.mrkaran.dev&#x2F;&quot;&gt;Doggo&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A command-line DNS Client for Humans, written in Golang.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ntfy.sh&#x2F;&quot;&gt;Ntfy&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A self-hosted push notification service.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;prom2grafana&quot;&gt;prom2grafana&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A tool to convert Prometheus metrics to Grafana dashboards and alert rules using AI.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;umami.is&#x2F;&quot;&gt;Umami&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A simple, fast, privacy-focused alternative to Google Analytics.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;service-highlights&quot;&gt;Service Highlights&lt;a class=&quot;zola-anchor&quot; href=&quot;#service-highlights&quot; aria-label=&quot;Anchor link for: service-highlights&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;technitium-a-powerful-dns-server&quot;&gt;Technitium: A Powerful DNS Server&lt;a class=&quot;zola-anchor&quot; href=&quot;#technitium-a-powerful-dns-server&quot; aria-label=&quot;Anchor link for: technitium-a-powerful-dns-server&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I came across Technitium DNS after seeing a recommendation from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;oddtazz&quot;&gt;@oddtazz&lt;&#x2F;a&gt;, and it has been a revelation. For anyone who wants more than just basic ad blocking from their DNS server, it’s a game-changer. It serves as both a recursive and authoritative server, meaning I don’t need a separate tool like &lt;code&gt;unbound&lt;&#x2F;code&gt; to resolve from root hints. The level of configuration is incredible—from DNSSEC, custom zones, and SOA records to fine-grained caching control.&lt;&#x2F;p&gt;
&lt;p&gt;The UI is a bit dated, but that’s a minor point for me given the raw power it provides. It is a vastly underrated tool for any homelabber who wants to go beyond Pi-hole or AdGuard Home.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;homelab-technitium.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab-technitium.png&quot; alt=&quot;Technitium DNS Server UI&quot; width=&quot;400&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;beszel-lightweight-monitoring&quot;&gt;Beszel: Lightweight Monitoring&lt;a class=&quot;zola-anchor&quot; href=&quot;#beszel-lightweight-monitoring&quot; aria-label=&quot;Anchor link for: beszel-lightweight-monitoring&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;For a long time, I felt that monitoring a homelab meant spinning up a full Prometheus and Grafana stack. Beszel is the perfect antidote to that complexity. It provides exactly what I need for basic node monitoring—CPU, memory, disk, and network usage—in a simple, lightweight package.&lt;&#x2F;p&gt;
&lt;p&gt;It’s incredibly easy to set up and provides a clean, real-time view of my servers without the overhead of a more complex system. For a simple homelab monitoring setup, it’s hard to beat.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;homelab-beszel-1.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab-beszel-1.png&quot; alt=&quot;Beszel Monitoring UI&quot; width=&quot;400&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;gatus-external-health-checks&quot;&gt;Gatus: External Health Checks&lt;a class=&quot;zola-anchor&quot; href=&quot;#gatus-external-health-checks&quot; aria-label=&quot;Anchor link for: gatus-external-health-checks&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;While Beszel monitors the servers from the inside, Gatus watches them from the outside. Running on an independent Hetzner VM, its job is to ensure my services are reachable from the public internet. It validates HTTP status codes, response times, and more.&lt;&#x2F;p&gt;
&lt;p&gt;This separation is crucial; if my entire home network goes down, Gatus is still online to send an alert to my phone. It’s the final piece of the puzzle for robust monitoring, ensuring I know when things are broken even if the monitoring service itself is part of the outage.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;homelab-gatus.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab-gatus.png&quot; alt=&quot;Gatus Health Checks UI&quot; width=&quot;400&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;storage-and-backup-strategy&quot;&gt;Storage and Backup Strategy&lt;a class=&quot;zola-anchor&quot; href=&quot;#storage-and-backup-strategy&quot; aria-label=&quot;Anchor link for: storage-and-backup-strategy&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Data integrity and recoverability are critical. My strategy is built on layers of redundancy and encryption.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;storage-btrfs-raid-1-luks-encryption&quot;&gt;Storage: BTRFS RAID 1 + LUKS Encryption&lt;a class=&quot;zola-anchor&quot; href=&quot;#storage-btrfs-raid-1-luks-encryption&quot; aria-label=&quot;Anchor link for: storage-btrfs-raid-1-luks-encryption&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I chose BTRFS for its modern features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Checksumming&lt;&#x2F;strong&gt;: Protects against silent data corruption.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Copy-on-Write&lt;&#x2F;strong&gt;: Enables instantaneous, low-cost snapshots.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Transparent Compression&lt;&#x2F;strong&gt;: &lt;code&gt;zstd&lt;&#x2F;code&gt; compression saves space without significant performance overhead.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The two 4TB drives are mirrored in a RAID 1 array, providing redundancy against a single drive failure. The entire array is encrypted using LUKS2, with the key stored on the boot SSD for automatic mounting. This protects data at rest in case of physical theft or drive disposal.&lt;&#x2F;p&gt;
&lt;p&gt;Mount options in &lt;code&gt;&#x2F;etc&#x2F;fstab&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&#x2F;dev&#x2F;mapper&#x2F;crypt-sda&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;mnt&#x2F;storage&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; btrfs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; defaults,noatime,compress=zstd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;backup-restic-cloudflare-r2&quot;&gt;Backup: Restic + Cloudflare R2&lt;a class=&quot;zola-anchor&quot; href=&quot;#backup-restic-cloudflare-r2&quot; aria-label=&quot;Anchor link for: backup-restic-cloudflare-r2&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;RAID does not protect against accidental deletion, file corruption, or catastrophic failure. My backup strategy follows the 3-2-1 rule.&lt;&#x2F;p&gt;
&lt;p&gt;Daily, automated backups are managed by systemd timers running &lt;code&gt;restic&lt;&#x2F;code&gt;. Backups are encrypted and sent to Cloudflare R2, providing an off-site copy. R2 was chosen for its zero-cost egress, which is a significant advantage for restores.&lt;&#x2F;p&gt;
&lt;p&gt;The backup script covers critical application data and the Docker Compose configurations:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;BACKUP_PATHS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;mnt&#x2F;storage&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; All application data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;home&#x2F;karan&#x2F;stacks&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Docker Compose configs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each backup run reports its status to a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;healthchecks.io&quot;&gt;healthchecks.io&lt;&#x2F;a&gt; endpoint, which sends a push notification on failure. I must appreciate its generous free tier, which is more than sufficient for my needs.&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;homelab-healthcheck.png&quot; class=&quot;lightbox-thumbnail&quot; data-featherlight=&quot;image&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;homelab-healthcheck.png&quot; alt=&quot;Healthchecks.io backup monitoring dashboard&quot; width=&quot;400&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This homelab represents a shift in philosophy from exploring complexity to valuing simplicity and reliability. The upfront hardware investment of ~$1,200 is offset by eliminating recurring cloud hosting costs and providing complete control over my data and services.&lt;&#x2F;p&gt;
&lt;p&gt;For those considering a homelab, my primary recommendation is to start with a simple, well-understood foundation. A reliable machine with a solid backup strategy is more valuable than a complex, hard-to-maintain cluster. The goal is to build a system that serves your needs, not one that you serve.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>TIL: WireGuard&#x27;s Misleading &quot;No Route to Host&quot; Error</title>
        <published>2025-07-30T00:00:00+00:00</published>
        <updated>2025-07-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/wireguard-route-fix/"/>
        <id>https://mrkaran.dev/posts/wireguard-route-fix/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/wireguard-route-fix/">&lt;p&gt;I recently spent some time debugging a WireGuard tunnel that was acting weird. The handshake was successful, pings worked perfectly, but any TCP connection failed with &lt;code&gt;connect: no route to host&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Classic misleading error message. The routing was fine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-setup&quot;&gt;The Setup&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-setup&quot; aria-label=&quot;Anchor link for: the-setup&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Server with a public IP running WireGuard (&lt;code&gt;wg0&lt;&#x2F;code&gt;) with IP &lt;code&gt;10.100.0.1&#x2F;24&lt;&#x2F;code&gt;. Client connects and gets assigned &lt;code&gt;10.100.0.2&#x2F;32&lt;&#x2F;code&gt;. I wanted to proxy TCP traffic from the server to a service running on the client at &lt;code&gt;10.100.0.2:7778&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-investigation&quot;&gt;The Investigation&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-investigation&quot; aria-label=&quot;Anchor link for: the-investigation&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Diagnostics showed contradictory results:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Routing worked fine:&lt;&#x2F;strong&gt; Server routing table correctly directed &lt;code&gt;10.100.0.0&#x2F;24&lt;&#x2F;code&gt; traffic to &lt;code&gt;wg0&lt;&#x2F;code&gt;. Pings were successful:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; On the server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.100.0.2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.100.0.2&lt;&#x2F;span&gt;&lt;span&gt; (10.100.0.2&lt;&#x2F;span&gt;&lt;span&gt;) 56(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;84&lt;&#x2F;span&gt;&lt;span&gt;) bytes of data.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.100.0.2:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; icmp_seq=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ttl=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; time=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;150&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;TCP failed immediately:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; On the server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http:&#x2F;&#x2F;10.100.0.2:7778&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; Trying 10.100.0.2:7778...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; connect to 10.100.0.2 port 7778 from 10.100.0.1 port 59812 failed: No route to host&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The key insight: &lt;code&gt;ICMP&lt;&#x2F;code&gt; was being treated differently than &lt;code&gt;TCP&lt;&#x2F;code&gt;. This pointed to a firewall issue, not routing. The “no route to host” error was the kernel interpreting an ICMP “Destination Unreachable” message from the remote peer.&lt;&#x2F;p&gt;
&lt;p&gt;But when I ran &lt;code&gt;tcpdump&lt;&#x2F;code&gt; on the client, things got stranger:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; On the client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tcpdump&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; any&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host 10.100.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Output when the server tries to connect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;17:36:03.043147&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; In&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.100.0.1.14808&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.100.0.2.7778:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [S&lt;&#x2F;span&gt;&lt;span&gt;], seq 324784341, win 42780, ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;TCP SYN&lt;&#x2F;code&gt; packet arrived successfully through &lt;code&gt;wg0&lt;&#x2F;code&gt;. But no response. No &lt;code&gt;SYN-ACK&lt;&#x2F;code&gt; (success), no &lt;code&gt;ICMP&lt;&#x2F;code&gt; error (rejection). The packet was being silently dropped.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-culprit-firewalld&quot;&gt;The Culprit: &lt;code&gt;firewalld&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-culprit-firewalld&quot; aria-label=&quot;Anchor link for: the-culprit-firewalld&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The client was running Arch Linux with &lt;code&gt;firewalld&lt;&#x2F;code&gt;. My mistake was trying to manage firewall rules with &lt;code&gt;iptables&lt;&#x2F;code&gt; commands in the WireGuard &lt;code&gt;PostUp&lt;&#x2F;code&gt; script. While &lt;code&gt;iptables&lt;&#x2F;code&gt; was installed, &lt;code&gt;firewalld&lt;&#x2F;code&gt; was the active manager, using &lt;code&gt;nftables&lt;&#x2F;code&gt; as its backend.&lt;&#x2F;p&gt;
&lt;p&gt;When a new interface like &lt;code&gt;wg0&lt;&#x2F;code&gt; comes up, &lt;code&gt;firewalld&lt;&#x2F;code&gt; needs to know which “zone” it belongs to. If unassigned, it gets handled by a restrictive default policy that silently &lt;code&gt;DROP&lt;&#x2F;code&gt;s unsolicited TCP packets while allowing ICMP (pings).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-fix&quot;&gt;The Fix&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-fix&quot; aria-label=&quot;Anchor link for: the-fix&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Don’t add &lt;code&gt;iptables&lt;&#x2F;code&gt; rules. Just assign the WireGuard interface to the right &lt;code&gt;firewalld&lt;&#x2F;code&gt; zone. For internal tunnels, &lt;code&gt;trusted&lt;&#x2F;code&gt; works well.&lt;&#x2F;p&gt;
&lt;p&gt;On the &lt;strong&gt;client&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; firewall-cmd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-permanent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-zone=trusted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-add-interface=wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; firewall-cmd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-reload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;TCP connections worked instantly after this.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;&#x2F;strong&gt; If WireGuard pings work but TCP fails with “no route to host”, it’s probably a client firewall issue. On &lt;code&gt;firewalld&lt;&#x2F;code&gt; systems, assign the WireGuard interface to the right zone instead of messing with &lt;code&gt;iptables&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Announcing Logchef</title>
        <published>2025-04-27T00:00:00+00:00</published>
        <updated>2025-04-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/announcing-logchef/"/>
        <id>https://mrkaran.dev/posts/announcing-logchef/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/announcing-logchef/">&lt;p&gt;So, for the last 3-4 months, I’ve been busy building &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;logchef.app&quot;&gt;Logchef&lt;&#x2F;a&gt;. This tool basically grew straight out of my day job managing logs at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zerodha.tech&quot;&gt;Zerodha&lt;&#x2F;a&gt;, where I’ve been managing logs for almost half a decade. I wanted to share a bit about how Logchef came to be.&lt;&#x2F;p&gt;
&lt;p&gt;Like many, we journeyed through the complexities of ELK (a management nightmare) and found its OSS fork, OpenSearch, didn’t quite hit the mark for us either. We eventually found solid ground with Clickhouse, as detailed on our tech blog: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zerodha.tech&#x2F;blog&#x2F;logging-at-zerodha&#x2F;&quot;&gt;Logging at Zerodha&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;challenges-faced-with-metabase&quot;&gt;Challenges Faced with Metabase&lt;a class=&quot;zola-anchor&quot; href=&quot;#challenges-faced-with-metabase&quot; aria-label=&quot;Anchor link for: challenges-faced-with-metabase&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;However, as I noted in that post, while Metabase served us well for analytics, it wasn’t the ideal UI specifically tailored for log analysis against Clickhouse:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“While Metabase has served us well so far, there is certainly room for improvement, especially regarding a more tailored UI for Clickhouse… we plan to continue exploring potential solutions.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Here’s a distilled version of the common pain points we experienced:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ad-hoc Querying Was Painful:&lt;&#x2F;strong&gt; Writing raw Clickhouse SQL in Metabase for quick log searches felt cumbersome and slow. Even modifying existing complex query templates was error-prone – a tiny syntax mistake could lead to minutes spent debugging the query itself, especially stressful during production incidents.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Disconnect Between Visualization and Raw Logs:&lt;&#x2F;strong&gt; A common workflow is to visualize trends (e.g., errors over time) and then drill down into the specific logs causing those trends. In Metabase, this often meant writing &lt;em&gt;two separate queries&lt;&#x2F;em&gt; – one for aggregation&#x2F;visualization and another (often rewritten from scratch) just to see the raw log lines. Metabase’s row limits (around 2k) further complicated viewing the full context of raw logs after filtering.
The intuitive “slice and drill-down” experience many log tools offer was missing.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;UI&#x2F;UX Annoyances:&lt;&#x2F;strong&gt; Several smaller but cumulative issues added friction: difficulty selecting precise time ranges like “last 6 hours,” viewing logs immediately surrounding a relevant event, columns getting truncated (&lt;code&gt;...&lt;&#x2F;code&gt;), and limited timestamp precision display in results. Though there are some workarounds, they often felt like band-aids rather than solutions.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;TL;DR: Metabase interface wasn’t optimized for the specific task of log exploration. Debugging sessions that &lt;em&gt;should&lt;&#x2F;em&gt; have taken minutes were stretching significantly longer. Querying and exploring logs felt clunkier than it needed to be.&lt;&#x2F;p&gt;
&lt;p&gt;And one fine day, &lt;strong&gt;I decided to stop just wishing for a better tool and start building one:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef_blog_1.png&quot; alt=&quot;Logchef&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;logchef&quot;&gt;Logchef&lt;a class=&quot;zola-anchor&quot; href=&quot;#logchef&quot; aria-label=&quot;Anchor link for: logchef&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When I first started prototyping, I kept the scope pretty tight: just build a viewer for the standard &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;specs&#x2F;otel&#x2F;logs&#x2F;data-model&#x2F;&quot;&gt;OTEL schema&lt;&#x2F;a&gt;. OTEL’s flexible enough, but a quick chat with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nadh.in&#x2F;&quot;&gt;Kailash&lt;&#x2F;a&gt;  sparked what turned out to be a game-changing idea: make Logchef schema-agnostic. And that really became the core concept.&lt;&#x2F;p&gt;
&lt;p&gt;Basically, Logchef lets you connect it straight to your existing Clickhouse log tables, no matter their structure. All it really needs is a timestamp field (&lt;code&gt;DateTime&lt;&#x2F;code&gt; or &lt;code&gt;DateTime64&lt;&#x2F;code&gt;). Bring your own custom schemas, stick with the OTEL standard, or even adapt it to your own needs. Logchef doesn’t force you into a specific format. From what I’ve seen, not many tools offer this kind of plug-and-play flexibility with existing tables today.&lt;&#x2F;p&gt;
&lt;p&gt;Logchef is designed as a specialized query and visualization layer sitting on top of Clickhouse. Logchef &lt;em&gt;intentionally&lt;&#x2F;em&gt; excludes log collection and ingestion. Why reinvent the wheel when excellent tools like Vector, Fluentbit, Filebeat, etc., already handle this reliably? Logchef focuses purely on exploring the logs once it’s in Clickhouse.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stack&quot;&gt;Stack&lt;a class=&quot;zola-anchor&quot; href=&quot;#stack&quot; aria-label=&quot;Anchor link for: stack&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Backend: Written in Go for performance and concurrency.&lt;&#x2F;li&gt;
&lt;li&gt;Metadata Storage: Uses SQLite for lightweight management of users, teams, Clickhouse source connections, and query collections. It’s simple and perfectly suited for this kind of a metadata store.&lt;&#x2F;li&gt;
&lt;li&gt;Frontend: An interactive log viewer with Vue.js and styled with shadcn&#x2F;ui and Tailwind CSS. I also implemented a simple search syntax for common filtering tasks (e.g., &lt;code&gt;status=200 and path~&quot;&#x2F;api&#x2F;&quot;&lt;&#x2F;code&gt;). This involved writing a tokenizer and parser that translates this syntax into efficient ClickHouse SQL conditions optimised for querying logs. Building this parser, validator, and integrating it smoothly with the Monaco editor for syntax highlighting was a significant effort but quite happy with the end result.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setting-up-the-public-demo-demo-logchef-app&quot;&gt;Setting Up the Public Demo (&lt;code&gt;demo.logchef.app&lt;&#x2F;code&gt;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-the-public-demo-demo-logchef-app&quot; aria-label=&quot;Anchor link for: setting-up-the-public-demo-demo-logchef-app&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;logchef_blog_2.png&quot; alt=&quot;Logchef Screenshot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I wanted a public &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;demo.logchef.app&quot;&gt;demo instance&lt;&#x2F;a&gt; so people could try Logchef easily. Setting this up involved a few specific tweaks compared to a standard deployment, all managed within the Docker Compose setup:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generating Dummy Data:&lt;&#x2F;strong&gt; A log viewer isn’t much use without logs! Instead of ingesting real data, I configured &lt;code&gt;vector&lt;&#x2F;code&gt; using its &lt;code&gt;demo_logs&lt;&#x2F;code&gt; source type. This continuously generates realistic-looking syslog and HTTP access logs and pushes them into the demo Clickhouse instance (&lt;code&gt;syslogs&lt;&#x2F;code&gt; and &lt;code&gt;http_logs&lt;&#x2F;code&gt; tables). It gives users immediate data to query without any setup on their part.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; vector.toml snippet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;generate_syslog&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;demo_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;format&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;syslog&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;interval&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0.3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Generate logs frequently&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sinks&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;clickhouse_syslog&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ... config to send to Clickhouse ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;table&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;syslogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Securing Admin Endpoints (Demo Mode):&lt;&#x2F;strong&gt; Since this is a public, shared instance, I wanted to prevent users from making potentially disruptive changes via the API (like deleting sources or teams). I used &lt;code&gt;Caddy&lt;&#x2F;code&gt; as the reverse proxy and configured it to intercept requests to admin-specific API routes (like &lt;code&gt;&#x2F;api&#x2F;v1&#x2F;admin&#x2F;*&lt;&#x2F;code&gt;) and block any method other than &lt;code&gt;GET&lt;&#x2F;code&gt;. If someone tries a &lt;code&gt;POST&lt;&#x2F;code&gt;, &lt;code&gt;PUT&lt;&#x2F;code&gt;, or &lt;code&gt;DELETE&lt;&#x2F;code&gt; to these endpoints, Caddy returns a &lt;code&gt;403 Forbidden&lt;&#x2F;code&gt; directly. This keeps the demo environment stable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Caddyfile snippet (conceptual)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;handle &#x2F;api&#x2F;v1&#x2F;admin&#x2F;* {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @block_methods method POST PUT DELETE PATCH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    respond @block_methods `{&amp;quot;error&amp;quot;:&amp;quot;Operation not permitted in demo mode&amp;quot;}` 403&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reverse_proxy logchef:8125 # Forward GET requests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Improving Demo Login UX:&lt;&#x2F;strong&gt; Logchef uses OIDC for authentication. For the demo, I’m running &lt;code&gt;Dex&lt;&#x2F;code&gt; as the OIDC provider. To make it completely frictionless for users, I didn’t want them needing to sign up or guess credentials. I simply customized Dex’s theme template for the login page to explicitly display the static demo username (&lt;code&gt;demo@logchef.app&lt;&#x2F;code&gt;) and password (&lt;code&gt;password&lt;&#x2F;code&gt;) right there. It’s a small UX tweak (again, thanks to Kailash for the idea!), but it means anyone landing on the demo can log in instantly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Dex login template snippet &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dex-info-box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;strong&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Demo Credentials:&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;strong&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;br&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Username: &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;code&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;demo@logchef.app&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;code&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;br&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Password: &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;code&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;password&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;code&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;input&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;demo@logchef.app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;input&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;password&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;password&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What’s Next?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-next&quot; aria-label=&quot;Anchor link for: what-s-next&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Logchef is already being used internally, but the journey towards a full v1.0 release continues this year. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;users&#x2F;mr-karan&#x2F;projects&#x2F;2&quot;&gt;roadmap&lt;&#x2F;a&gt; includes exciting additions like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Alerting: Trigger notifications based on query results.&lt;&#x2F;li&gt;
&lt;li&gt;Live Tail Logs: Stream logs in real-time.&lt;&#x2F;li&gt;
&lt;li&gt;Enhanced Dashboarding: More powerful visualization capabilities.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Logchef is open source (AGPLv3), and community involvement is welcomed. You can check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;demo.logchef.app&#x2F;&quot;&gt;Demo&lt;&#x2F;a&gt; or view the code on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;logchef&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you have more ideas or features you’d like to see, please reach out on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;logchef&#x2F;issues&quot;&gt;GitHub&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;contact&#x2F;&quot;&gt;email me&lt;&#x2F;a&gt;! I’m always open to suggestions and feedback.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly, building Logchef has been incredibly rewarding. It started as a way to fix something that bugged me (and others!), and seeing it turn into a tool I’m genuinely excited about feels great.&lt;&#x2F;p&gt;
&lt;p&gt;I couldn’t have done it alone, though. I’m really grateful to my friends and colleagues who jumped in with feedback along the way. Huge thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nadh.in&#x2F;&quot;&gt;Kailash&lt;&#x2F;a&gt; for the constant support and encouragement, and to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vivekr.dev&#x2F;&quot;&gt;Vivek&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sarat.dev&#x2F;&quot;&gt;Sarat&lt;&#x2F;a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rhnvrm&#x2F;&quot;&gt;Rohan&lt;&#x2F;a&gt; for testing the early builds and offering great suggestions.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, a big thank you to my wife, who patiently endured my late-night coding sessions. Her support means the world to me &amp;lt;3&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Trying out NixOS</title>
        <published>2025-03-23T10:15:00+05:30</published>
        <updated>2025-03-23T10:15:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/trying-nixos/"/>
        <id>https://mrkaran.dev/posts/trying-nixos/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/trying-nixos/">&lt;p&gt;I’ve been introduced to Nix by my colleagues at work. Being a Linux user for over a decade and a serial distro hopper, I was curious to learn more about it. I’d seen Nix mentioned before, but the comments about its steep learning curve made me wonder if the effort was worth it. I decided to give it a try by reading this excellent &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nixos-and-flakes.thiscute.world&quot;&gt;beginner’s guide&lt;&#x2F;a&gt; however got bored very quickly and decided to “learn on the fly”. I spun up a VM in my homelab to install NixOS using their &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nixos.org&#x2F;download&#x2F;&quot;&gt;official GUI installer image&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation-first-impressions&quot;&gt;Installation &amp;amp; First Impressions&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation-first-impressions&quot; aria-label=&quot;Anchor link for: installation-first-impressions&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The installation was as straightforward as any other Linux distro. NixOS is a declarative operating system that leverages the Nix functional package manager and a rich ecosystem of Nix packages. The flexibility is mind-blowing: you can configure everything—from user accounts and SSH keys to &lt;code&gt;$SHELL&lt;&#x2F;code&gt; config and plugins entirely through code.&lt;&#x2F;p&gt;
&lt;p&gt;Once installed, the first place you’d want to poke around is the &lt;code&gt;&#x2F;etc&#x2F;nixos&lt;&#x2F;code&gt; directory, which contains two essential configuration files:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;hardware-configuration.nix&lt;&#x2F;code&gt;: Generated during installation (or regenerated with commands like &lt;code&gt;nixos-generate-config&lt;&#x2F;code&gt;), it has hardware-specific details such as filesystem mount points, disk configurations, kernel modules etc. See an example file &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fooblahblah&#x2F;nixos&#x2F;blob&#x2F;master&#x2F;hardware-configuration.nix&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;configuration.nix&lt;&#x2F;code&gt;: This is &lt;em&gt;the most&lt;&#x2F;em&gt; important file you want to start editing with. Here you define system-wide settings like timezone, locale, user accounts, and networking. Everything is declared in one place, making your system’s state reproducible.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;first-configuration-changes&quot;&gt;First Configuration Changes&lt;a class=&quot;zola-anchor&quot; href=&quot;#first-configuration-changes&quot; aria-label=&quot;Anchor link for: first-configuration-changes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When I opened the terminal, I immediately noticed that &lt;code&gt;vim&lt;&#x2F;code&gt; wasn’t installed. So, I updated my &lt;code&gt;configuration.nix&lt;&#x2F;code&gt; to include the packages I needed:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;systemPackages&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; pkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;  git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;  vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After saving, I ran:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nixos-rebuild&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; switch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This rebuilds the system using the new declarative configuration.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;version-control-flakes&quot;&gt;Version Control &amp;amp; Flakes&lt;a class=&quot;zola-anchor&quot; href=&quot;#version-control-flakes&quot; aria-label=&quot;Anchor link for: version-control-flakes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Next, I wanted to set up version control for my Nix configurations. The key takeaway is that while the system’s state is revertable in NixOS, your personal data (which includes &lt;code&gt;configuration.nix&lt;&#x2F;code&gt;) isn’t automatically backed up. You must manage your own version history for your Nix configs. Since I was tweaking with no knowledge of Nix, having a version history was crucial.&lt;&#x2F;p&gt;
&lt;p&gt;I moved my &lt;code&gt;&#x2F;etc&#x2F;nixos&lt;&#x2F;code&gt; configs to &lt;code&gt;~&#x2F;Code&#x2F;nixos-configs&lt;&#x2F;code&gt; and initialized a Git repository:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Create repo in home directory (better than root-owned &#x2F;etc&#x2F;nixos)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ~&#x2F;nixos-config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;nixos&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ~&#x2F;nixos-config&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ~&#x2F;nixos-config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Initialize Git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; add&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Initial NixOS configuration&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add GitHub remote&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; add&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; origin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; https:&#x2F;&#x2F;github.com&#x2F;username&#x2F;nixos-config.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; push&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; origin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here’s how &lt;code&gt;flake.nix&lt;&#x2F;code&gt; looks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;  description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;NixOS configuration for Karan&amp;#39;s homelab, servers, and personal dev machines&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;  inputs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;    nixpkgs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;github:nixos&#x2F;nixpkgs&#x2F;nixos-unstable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add agenix as an input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;    agenix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;      url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;github:ryantm&#x2F;agenix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;      inputs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;nixpkgs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;follows&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nixpkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Optionally add other inputs like home-manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; home-manager = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;   url = &amp;quot;github:nix-community&#x2F;home-manager&#x2F;release-24.11&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;   inputs.nixpkgs.follows = &amp;quot;nixpkgs&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;  outputs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; agenix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; nixpkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;@&lt;&#x2F;span&gt;&lt;span&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Make agenix available as a package&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;    packages&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;x86_64-linux&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;agenix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; agenix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;packages&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;x86_64-linux&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;    nixosConfigurations&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; nixpkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;lib&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;nixosSystem&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;      system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x86_64-linux&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;      modules&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        .&#x2F;configuration.nix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;        agenix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;nixosModules&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add agenix module&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;a-note-on-flakes&quot;&gt;A Note on Flakes&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-note-on-flakes&quot; aria-label=&quot;Anchor link for: a-note-on-flakes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Flakes are an experimental (although widely adopted in the community) feature in Nix that bring reproducibility, composability, and a standardized structure to your configurations and package definitions. They allow you to declare all inputs (like nixpkgs, home-manager, or other repositories) and outputs (such as system configurations, packages, or development shells) in a single file. Flakes also create a lock file (&lt;code&gt;flake.lock&lt;&#x2F;code&gt;) that pins your dependencies to specific revisions, ensuring that your builds remain reproducible over time.&lt;&#x2F;p&gt;
&lt;p&gt;I learned the hard way that—even for local configurations you must commit your files. Otherwise, you may see errors like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;nix&#x2F;store&#x2F;...source&#x2F;flake.nix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; does&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; exist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even if you’re using local paths and have no intention to push to &lt;code&gt;git&lt;&#x2F;code&gt;, you still need &lt;code&gt;git init&lt;&#x2F;code&gt; &amp;amp;&amp;amp; &lt;code&gt;git add&lt;&#x2F;code&gt; for flakes to work.
From whatever google-fu I did, it seems this requirement is to ensure that flakes can reliably reference the exact content in your configuration.
I am sure there might be good reasons for it (as I said before, I’ve skipped RTFMing altogether ^_^), but atleast the errors can be more verbose&#x2F;helpful.&lt;&#x2F;p&gt;
&lt;p&gt;And why I skipped docs: Remember, we’re on a mission to get things up and running with Nix and then &lt;em&gt;later&lt;&#x2F;em&gt; spend time about reading their internals if it actually proves to be a valuable experiment.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;switching-channels&quot;&gt;Switching Channels&lt;a class=&quot;zola-anchor&quot; href=&quot;#switching-channels&quot; aria-label=&quot;Anchor link for: switching-channels&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;While installing packages, I noticed some packages were quite outdated. That’s when I learned about NixOS channels. Think of channels as analogous to LTS releases. For faster updates, you can switch to the &lt;code&gt;unstable&lt;&#x2F;code&gt; channel. Although the name sounds intimidating, it simply means you’ll receive more frequent package updates.&lt;&#x2F;p&gt;
&lt;p&gt;To do this, you can edit your &lt;code&gt;flake.nix&lt;&#x2F;code&gt; and switch the URL to an unstable channel:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  inputs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nixpkgs.url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;github:NixOS&#x2F;nixpkgs&#x2F;nixos-24.11&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Stable channel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nixpkgs.url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;github:NixOS&#x2F;nixpkgs&#x2F;nixos-unstable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Unstable channel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;firmware-updates&quot;&gt;Firmware Updates&lt;a class=&quot;zola-anchor&quot; href=&quot;#firmware-updates&quot; aria-label=&quot;Anchor link for: firmware-updates&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After setting up packages, it was time to configure firmware updates using &lt;code&gt;fwupd—essential&lt;&#x2F;code&gt; for keeping your hardware up to date.&lt;&#x2F;p&gt;
&lt;p&gt;I asked Claude to help me for a quick setup. Here’s what I did:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; config&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; pkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;  services&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;fwupd&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;enable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then run a rebuild:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nixos-rebuild&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; switch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once enabled, you can use the &lt;code&gt;fwupdmgr&lt;&#x2F;code&gt; command-line tool to manage firmware updates:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Refresh metadata and check for available updates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;fwupdmgr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; refresh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;fwupdmgr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get-updates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Install available firmware updates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;fwupdmgr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;fine-tuning&quot;&gt;Fine Tuning&lt;a class=&quot;zola-anchor&quot; href=&quot;#fine-tuning&quot; aria-label=&quot;Anchor link for: fine-tuning&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I also tweaked some settings for the Nix package manager to optimize builds, caching, and overall performance. Here’s a snippet from my configuration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Nix package manager optimizations&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  nix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    settings&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Optimize store to remove duplicate files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      auto-optimise-store&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Allow building multiple derivations in parallel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      max-jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Number of parallel build tasks per job&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      cores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; 0 means use all available cores&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Use the binary cache aggressively&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      substituters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;lt;https:&#x2F;&#x2F;cache.nixos.org&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;lt;https:&#x2F;&#x2F;nix-community.cachix.org&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;lt;https:&#x2F;&#x2F;nixpkgs-wayland.cachix.org&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Optimize fetching from GitHub&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      connect-timeout&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Prevent unneeded rebuilds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      commit-lockfile-summary&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Update flake.lock&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Garbage collection settings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    gc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      automatic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      dates&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;weekly&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      options&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--delete-older-than 30d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Optimize builds using different build cores&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    buildCores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; 0 means use all available cores&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Enable flakes and modern Nix command features&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    extraOptions&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      experimental-features&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nix-command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; flakes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      warn-dirty&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      keep-going&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      log-lines&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 20&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;escape-hatches&quot;&gt;Escape Hatches&lt;a class=&quot;zola-anchor&quot; href=&quot;#escape-hatches&quot; aria-label=&quot;Anchor link for: escape-hatches&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So far things seems all rosy. Within just spending a couple of minutes - I had a perfectly working machine for myself - and the best part - all reproducible with a single command. I was starting to see why people who use NixOS preach about it so much.&lt;&#x2F;p&gt;
&lt;p&gt;However, not everything is smooth when you deviate from the happy path. For instance, I use &lt;a href=&quot;&#x2F;posts&#x2F;using-llm&#x2F;&quot;&gt;Aider&lt;&#x2F;a&gt; for LLM assisted programming, but the version on Nixpkgs was about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;NixOS&#x2F;nixpkgs&#x2F;blob&#x2F;nixos-unstable&#x2F;pkgs&#x2F;development&#x2F;python-modules&#x2F;aider-chat&#x2F;default.nix#L16&quot;&gt;three minor versions&lt;&#x2F;a&gt; behind. Typically for any other software, I wouldn’t have cared so much - however with these LLM tools, a lot changes rapidly and I didn’t want to stay behind. Besides, it seemed like a fun exercise in getting my hands dirty by installing a Python package on NixOS which turned out to be quite tricky because Nix is absurdly obsessive about fully isolated builds.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s an example flake that I used for attempting to install Aider with &lt;code&gt;uv&lt;&#x2F;code&gt;  in a dev shell (which didn’t work btw):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;  description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Aider development environment&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;  inputs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;    nixpkgs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;github:NixOS&#x2F;nixpkgs&#x2F;nixos-unstable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;    flake-utils&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;github:numtide&#x2F;flake-utils&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;  outputs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; nixpkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; flake-utils&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;    flake-utils&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;lib&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;eachDefaultSystem&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;system&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;      let&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;        pkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; nixpkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;legacyPackages&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;      in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;        devShell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; pkgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;mkShell&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;          buildInputs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; pkgs&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;            python312&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;            uv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          ]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;          shellHook&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            export PATH=&amp;quot;$HOME&#x2F;.local&#x2F;bin:$PATH&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Entering the dev shell with &lt;code&gt;nix develop&lt;&#x2F;code&gt; and installing Aider with &lt;code&gt;uv&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;uv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-force&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-python&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; python3.12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; aider-chat@latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, I ran into this error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&#x2F;home&#x2F;karan&#x2F;.local&#x2F;share&#x2F;uv&#x2F;tools&#x2F;aider-chat&#x2F;lib&#x2F;python3.12&#x2F;site-packages&#x2F;litellm&#x2F;litellm_core_uti&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ls&#x2F;llm_cost_calc&#x2F;utils.py&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;modul&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; litellm.utils&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get_model_info&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  File&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&#x2F;home&#x2F;karan&#x2F;.local&#x2F;share&#x2F;uv&#x2F;tools&#x2F;aider-chat&#x2F;lib&#x2F;python3.12&#x2F;site-packages&#x2F;litellm&#x2F;utils.py&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;53,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;modul&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tokenizers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Tokenizer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  File&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&#x2F;home&#x2F;karan&#x2F;.local&#x2F;share&#x2F;uv&#x2F;tools&#x2F;aider-chat&#x2F;lib&#x2F;python3.12&#x2F;site-packages&#x2F;tokenizers&#x2F;__init__.py&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 78,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;modul&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .tokenizers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ImportError:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; libstdc++.so.6:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cannot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; open&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; shared&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; object&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; file:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; No&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; such&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The error indicated that Aider was missing a required dependency &lt;code&gt;libstdc++.so.6&lt;&#x2F;code&gt; which is a part of the C++ standard library needed by the tokenizers package. To fix this, I added &lt;code&gt;stdenv.cc.cc.lib&lt;&#x2F;code&gt; (and even &lt;code&gt;gcc&lt;&#x2F;code&gt; to be on the safer side) to my &lt;code&gt;buildInputs&lt;&#x2F;code&gt;. This is because while &lt;code&gt;uv&lt;&#x2F;code&gt; installs Python packages, it doesn’t handle system-level dependencies. In a Nix environment, every dependency, including system libraries, must be explicitly specified.&lt;&#x2F;p&gt;
&lt;p&gt;Frankly, Python’s packaging ecosystem is still a mess. Although tools like &lt;code&gt;uv&lt;&#x2F;code&gt; help, achieving a completely isolated build, especially when shared libraries are involved is challenging. I wish the Python community would put more effort into resolving these issues.&lt;&#x2F;p&gt;
&lt;p&gt;While I was able to make &lt;code&gt;aider&lt;&#x2F;code&gt; work by explicitly adding all the dependencies, I faced another outdate package: &lt;code&gt;code-cursor&lt;&#x2F;code&gt;. Since this is a full blown electron app, I didn’t wish to package this myself.&lt;&#x2F;p&gt;
&lt;p&gt;After some frustration, I tried using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;distrobox.it&#x2F;&quot;&gt;Distrobox&lt;&#x2F;a&gt; as recommended by a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.trieoflogs.com&#x2F;&quot;&gt;colleague&lt;&#x2F;a&gt;. Distrobox lets you run containers that feel almost like a native OS by managing user IDs, host mounts, network interfaces, and more. I used an Arch Linux image, installed &lt;code&gt;cursor-bin&lt;&#x2F;code&gt; from the AUR, and everything worked fine. Well mostly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Fonts were missing. So, if I want to use custom fonts in my IDE - I need to have them installed in the container as well.&lt;&#x2F;li&gt;
&lt;li&gt;Since my &lt;code&gt;fish&lt;&#x2F;code&gt; shell config had &lt;code&gt;export EDITOR=nvim&lt;&#x2F;code&gt;, I had to install &lt;code&gt;neovim&lt;&#x2F;code&gt; in the container as well, otherwise, I’d get an error when trying to &lt;code&gt;git commit&lt;&#x2F;code&gt; etc. There’s an option to customise the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;distrobox.it&#x2F;useful_tips&#x2F;#use-a-different-shell-than-the-host&quot;&gt;shell&lt;&#x2F;a&gt; in distrobox, but for whatever reason (that I didn’t want to debug), it didn’t work for me.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Yet, something still felt off. The whole point of using NixOS is to achieve a fully declarative and reproducible setup. Resorting to an escape hatch like Distrobox undermines that goal. So I was very conflicted about this. I’m sure there’s a better way to handle these situations, and I should probably read the docs to find out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’m definitely sold on running NixOS, especially when managing multiple systems. With a single declarative file (&lt;code&gt;configuration.nix&lt;&#x2F;code&gt;), duplicating your setup across machines becomes effortless. No more “documenting” (or rather &lt;em&gt;forgetting&lt;&#x2F;em&gt; to document and keeping it updated)- as the config is the single source of truth.&lt;&#x2F;p&gt;
&lt;p&gt;Fun fact: I even messed up my NixOS build by misconfiguring the &lt;code&gt;hardware-configuration.nix&lt;&#x2F;code&gt;, and my system became unusable even after a reboot, it couldn’t mount the filesystem on the correct device. In other distros, that would have sent me into panic mode, but with NixOS, all I had to do was revert to the previous working state, and everything was fine. That was so cool!&lt;&#x2F;p&gt;
&lt;p&gt;I’m definitely considering moving my homelab to NixOS in the coming few days because I honestly see the value for a server setup. I often set up my personal server and then forget everything I’ve done and I’m always scared of touching or creating a new server from scratch. I even created a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;junbi&quot;&gt;small shell script installer&lt;&#x2F;a&gt; to help me for getting a base system ready. But like this shell script or even tools such as Ansible - they are all idempotent in nature. However in Nix, if I remove a certain piece from the configuration, there isn’t a trace of it left on the system. That makes it truly declarative and reproducible - unlike Ansible where you can still have some parts of the old setup.&lt;&#x2F;p&gt;
&lt;p&gt;However, for my primary machine at work, I’ll wait on the sidelines until the packages I depend on resolve their dependency issues and I get a chance to read up more on the escape hatches I tried to see if there’s a more streamlined way of doing things. I might be missing a lot of fundamental details since I skipped the docs entirely to get my hands dirty. But now that I see the value of a declarative system and especially how easy it is to roll back the machine to a previously known good state, I’m motivated to read up more on this and might post an update to this blog.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Automating Badminton Game Alerts</title>
        <published>2025-03-04T00:10:55+05:30</published>
        <updated>2025-03-04T00:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/playo-badminton/"/>
        <id>https://mrkaran.dev/posts/playo-badminton/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/playo-badminton/">&lt;p&gt;I’ve been playing badminton more regularly since the start of 2025 - almost 4-5 days a week. I recently moved to a new part of the city, which meant I couldn’t play with my old friends anymore. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;playo.co&#x2F;&quot;&gt;PlayO&lt;&#x2F;a&gt; has been super helpful for finding games with new people. On PlayO, a host creates a game and up to 6 people can join one court for a one-hour badminton doubles session.&lt;&#x2F;p&gt;
&lt;p&gt;However, on hectic days I would often forget to check for badminton games, only to find them fully booked later. I wanted to automate this process by creating a small script that would send me scheduled alerts about today’s game availability, allowing me to book slots before they filled up. I drew inspiration from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mattrighetti.com&#x2F;2025&#x2F;03&#x2F;03&#x2F;reverse-engineering-playtomic&quot;&gt;Matt’s&lt;&#x2F;a&gt; post where he did something similar.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, PlayO has a public API endpoint to retrieve a list of available games: &lt;code&gt;https:&#x2F;&#x2F;api.playo.io&#x2F;activity-public&#x2F;list&#x2F;location&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can send a &lt;code&gt;POST&lt;&#x2F;code&gt; request to this URL with these parameters for filtering:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;lat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 12.9783692&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;lng&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 77.6408356&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;cityRadius&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;gameTimeActivities&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;page&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;lastId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;sportId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;SP5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;booking&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2025-03-04T11:03:17.260Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It returns a list of activities matching these filters. One such activity looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;profilePicUrl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;playov2.gumlet.io&#x2F;profiles&#x2F;redacted.511716.jpg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;fName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;lName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;karma&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;profilePicUrl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;playov2.gumlet.io&#x2F;profiles&#x2F;redacted-redacted.png&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;fName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;lName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;karma&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 499&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;isPlayoGame&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;skill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Intermediate &amp;amp; above&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;sportName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Badminton&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;shortListed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;joineeList&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7f3cf298-3324-4fc2-96ad-b0f00093cd8f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;250572a2-555d-4a77-94f0-452142c08f81&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cc3b9eb6-a3b5-4c26-8605-0486fa000a4b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8d5d4299-950b-4011-a7ac-b466b1c00e84&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;235ae56d-6f4f-4106-9304-fb38e7d4add8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;isPlaypalPlaying&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;lat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 12.976394040119704&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;lng&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 77.63644146986815&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Game Theory - Double Road Indiranagar, Indiranagar&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;joineeCount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;sportsPlayingMode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;icon&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;maxPlayers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;full&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;price&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;startTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2025-03-04T13:30:00.000Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;endTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2025-03-04T15:30:00.000Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;minSkill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;maxSkill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;skillSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;booking&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;bookingId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;venueId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;82af038f-058c-4b2f-bc3d-3a47910d4f97&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;venueName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Game Theory - Double Road Indiranagar, Indiranagar&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;activityType&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;regular&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;isOnline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;groupId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;groupName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;currencyTxt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;INR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;strictSkill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2025-03-04T00:00:00.000Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;hostId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;sportId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;SP5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;timing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e2ee9f62-c9b6-472b-aea2-b0c52dd7c525&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;distance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0.5249236963063415&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;courtInfo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;sponsored&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;groups&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using the above response, I filtered for games where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;full&lt;&#x2F;code&gt; is &lt;code&gt;false&lt;&#x2F;code&gt; (This indicates that &lt;code&gt;joineeCount == maxPlayer&lt;&#x2F;code&gt; is not true, meaning spots are still available to join)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;startTime&lt;&#x2F;code&gt; and &lt;code&gt;endTime&lt;&#x2F;code&gt; fall within 7-8PM IST&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I also wanted to add a feature to send these details to Telegram for convenient notifications. I then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;karpathy&#x2F;status&#x2F;1886192184808149383&quot;&gt;vibe coded&lt;&#x2F;a&gt; with Claude 3.7 to create a Python script to automate this whole process. Impressively, it produced a working script pretty much in a one-shot prompt, though I had to make a few minor tweaks. I quite like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;simonwillison.net&#x2F;2024&#x2F;Dec&#x2F;19&#x2F;one-shot-python-tools&#x2F;&quot;&gt;Simon Willison’s approach&lt;&#x2F;a&gt; of using &lt;code&gt;uv&lt;&#x2F;code&gt; to build one-shot tools. Managing dependencies, virtual environments, etc. is still a pain point in Python, but using &lt;code&gt;uv&lt;&#x2F;code&gt; feels like magic by comparison.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&#x2F; script&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; requires-python = &amp;quot;&amp;gt;=3.12&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; dependencies = [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;     &amp;quot;click&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;     &amp;quot;requests&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;     &amp;quot;pytz&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;     &amp;quot;rich&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;     &amp;quot;python-dateutil&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;     &amp;quot;python-telegram-bot&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; click&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; requests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; datetime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; pytz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; sys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; rich&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;console&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Console&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; rich&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;table&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; dateutil&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; parser&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; telegram&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Bot&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; InputMediaPhoto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; telegram&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;constants&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; ParseMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; io&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; BytesIO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;console&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Console&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--lat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12.9783692&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Latitude for search&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--lng&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;77.6408356&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Longitude for search&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--radius&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;City radius in km&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--sport&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;SP5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Sport ID (default: SP5 for Badminton)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--start-time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;19:00&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Desired start time (24-hour format HH:MM)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--end-time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;20:00&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Desired end time (24-hour format HH:MM)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--timezone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Asia&#x2F;Kolkata&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Your timezone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--verbose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; is_flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Show detailed information including exact UTC&#x2F;IST times&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--include-full&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; is_flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Include games that are full&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--telegram&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; is_flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Send results to Telegram&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--telegram-token&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; envvar&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;TELEGRAM_BOT_TOKEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Telegram Bot Token (or set TELEGRAM_BOT_TOKEN env var)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;click&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;option&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--telegram-chat-id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; envvar&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;TELEGRAM_CHAT_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Telegram Chat ID (or set TELEGRAM_CHAT_ID env var)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; find_games&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;lat&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; lng&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; radius&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sport&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; start_time&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; end_time&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; timezone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; verbose&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; include_full&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; telegram&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; telegram_token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; telegram_chat_id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Find available badminton games on Playo matching your criteria.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Get today&amp;#39;s date in the specified timezone&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    local_tz&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; pytz&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;timezone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;timezone&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    now&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; datetime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;datetime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;local_tz&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    today_date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; now&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strftime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%Y-%m-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T%H:%M:%S.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Parse desired time window&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        desired_start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; datetime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;datetime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strptime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;start_time&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%H:%M&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        desired_end&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; datetime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;datetime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strptime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;end_time&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%H:%M&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; ValueError&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error:[&#x2F;bold red] Invalid time format. Please use HH:MM (24-hour format).&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold green]Searching for badminton games around your location...[&#x2F;bold green]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Looking for games between [bold]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;start_time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[&#x2F;bold] and [bold]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;end_time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[&#x2F;bold] IST today&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; verbose&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[dim]Search parameters: lat=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;lat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;, lng=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;lng&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;, radius=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;radius&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;km[&#x2F;dim]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[dim]Current time in &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;timezone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;now&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strftime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%Y-%m-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; %H:%M:%S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[&#x2F;dim]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Prepare API request&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;api.playo.io&#x2F;activity-public&#x2F;list&#x2F;location&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    payload&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; lat&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lng&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; lng&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cityRadius&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; radius&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;gameTimeActivities&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; False&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;page&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lastId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sportId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;sport&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;booking&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; False&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;today_date&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    headers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Content-Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;application&#x2F;json&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;User-Agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Mozilla&#x2F;5.0 (Windows NT 10.0; Win64; x64) AppleWebKit&#x2F;537.36 (KHTML, like Gecko) Chrome&#x2F;91.0.4472.124 Safari&#x2F;537.36&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        response&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; requests&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;url&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; headers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;headers&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; json&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;payload&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        response&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;raise_for_status&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;json&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;requestStatus&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error:[&#x2F;bold red] Failed to get valid response from Playo API&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Process activities&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        activities&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;activities&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; activities&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[yellow]No badminton activities found for today[&#x2F;yellow]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Filter activities based on criteria&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        matching_games&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; activities&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Convert UTC times to local timezone&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            start_time_utc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;startTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            end_time_utc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;endTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            start_time_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; start_time_utc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;astimezone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;local_tz&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            end_time_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; end_time_utc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;astimezone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;local_tz&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Print all times in debug mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; console.print(f&amp;quot;DEBUG: {activity.get(&amp;#39;location&amp;#39;, &amp;#39;Unknown&amp;#39;)} - Start: {start_time_local.strftime(&amp;#39;%H:%M&amp;#39;)} IST (UTC: {start_time_utc.strftime(&amp;#39;%H:%M&amp;#39;)})&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Convert time objects correctly for comparison&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            start_hour&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; start_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;hour&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            start_minute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; start_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;minute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Convert desired times to hours and minutes for easier comparison&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            desired_start_hour&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; desired_start&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;hour&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            desired_start_minute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; desired_start&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;minute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            desired_end_hour&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; desired_end&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;hour&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            desired_end_minute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; desired_end&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;minute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Check if this game starts at 7PM (19:00) and ends at 8PM (20:00)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            is_time_match&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Get duration in minutes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            duration_minutes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;end_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;hour&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; end_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;minute&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                               (&lt;&#x2F;span&gt;&lt;span&gt;start_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;hour&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; start_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;minute&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Check if start time is 7PM (with small tolerance)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;start_hour&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span&gt; desired_start_hour&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; and&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                start_minute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span&gt; desired_start_minute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; and&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                start_minute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; desired_start_minute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Allow a small window of 10 minutes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;                #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Check if duration is approximately 1 hour (between 50-70 minutes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 50&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span&gt; duration_minutes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 70&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    is_time_match&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Check if there are available slots&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            is_available&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                not&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;full&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; and&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                (&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;maxPlayers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; or&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;joineeCount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;maxPlayers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; When verbose, print time details for each game to help debug&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; verbose&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                time_info&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[dim]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Unknown&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; - Start: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;start_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strftime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%H:%M&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IST (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;start_time_utc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strftime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%H:%M&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; UTC), &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                           f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;End: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;end_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strftime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%H:%M&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IST, Duration: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;duration_minutes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; min, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                           f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Time match: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Yes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; is_time_match&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;No&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;, Available: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Yes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; is_available&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;No&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[&#x2F;dim]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;time_info&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Both conditions must be true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; is_time_match&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span&gt; is_available&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                matching_games&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;venue_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;venueName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&#x2F;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; start_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strftime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%I:%M %p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; end_time_local&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strftime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%I:%M %p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;players&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;joineeCount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;maxPlayers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;unlimited&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;fName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Unknown&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;skill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;skill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Any&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;price&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;price&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt;activity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;currencyTxt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;INR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Display results&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; matching_games&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            table&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Table&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Available Badminton Games (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;matching_games&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; matches found)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_column&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Location&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cyan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_column&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_column&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Players&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;yellow&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_column&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;magenta&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_column&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Skill Level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;blue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_column&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Link&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bright_blue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            for&lt;&#x2F;span&gt;&lt;span&gt; game&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; matching_games&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add_row&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                    f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;venue_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                    f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; - &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;players&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;skill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                    f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;playo.co&#x2F;match&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;table&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Send to Telegram if requested&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; telegram&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; telegram_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; telegram_chat_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error:[&#x2F;bold red] Telegram token and chat ID are required for Telegram notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[dim]Set them with --telegram-token and --telegram-chat-id or via environment variables[&#x2F;dim]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                    try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        send_to_telegram&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;matching_games&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; telegram_token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; telegram_chat_id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[green]Results sent to Telegram successfully![&#x2F;green]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                    except&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error sending to Telegram:[&#x2F;bold red] &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[yellow]No games found matching your criteria[&#x2F;yellow]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; telegram&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span&gt; telegram_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span&gt; telegram_chat_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    asyncio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;send_telegram_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;No badminton games found matching your criteria for today.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        telegram_token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        telegram_chat_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    )&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[green]Empty results notification sent to Telegram[&#x2F;green]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                except&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error sending to Telegram:[&#x2F;bold red] &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span&gt; requests&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;RequestException&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error:[&#x2F;bold red] Failed to connect to Playo API: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span&gt; json&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;JSONDecodeError&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error:[&#x2F;bold red] Failed to parse API response&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[bold red]Error:[&#x2F;bold red] An unexpected error occurred: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; send_to_telegram&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;games&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chat_id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Send game information to Telegram as a nicely formatted message.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; games&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Create a formatted message for Telegram&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;🏸 *Available Badminton Games* 🏸&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; game&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; enumerate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;games&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;venue_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;⏰ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; - &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;👥 Players: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;players&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;👤 Host: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;🎯 Skill: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;skill&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;🔗 [Join Game](https:&#x2F;&#x2F;playo.co&#x2F;match&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;game&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Send the message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    asyncio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;send_telegram_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chat_id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;async&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; send_telegram_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chat_id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Send a message to Telegram using the Bot API.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    bot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Bot&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;token&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;token&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; bot&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;send_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;        chat_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;chat_id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;        text&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;        parse_mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;ParseMode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;MARKDOWN&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;        disable_web_page_preview&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    find_games&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The script outputs a beautiful output:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;badminton_cli.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Telegram:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;badminton_tg.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scheduling&quot;&gt;Scheduling&lt;a class=&quot;zola-anchor&quot; href=&quot;#scheduling&quot; aria-label=&quot;Anchor link for: scheduling&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I wanted this script to run reliably every day and used GitHub Actions for that.
GitHub Actions felt like the path of least resistance as I didn’t have to worry about keeping a server running or getting alerts if something crashed. For a small personal script like this, it was the perfect “set it and forget it” solution.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;adminton Game Checker Base&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;chedule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Run Monday to Friday at 12:00 PM IST (6:30 AM UTC)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ron&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;30 6 * * 1-5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;heck-games&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;buntu-latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ELEGRAM_BOT_TOKEN&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ secrets.TELEGRAM_BOT_TOKEN }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ELEGRAM_CHAT_ID&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ secrets.TELEGRAM_CHAT_ID }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      L&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ATITUDE&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ inputs.latitude }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      L&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ONGITUDE&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ inputs.longitude }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ADIUS&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ inputs.radius }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;PORT_ID&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ inputs.sport_id }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;IMEZONE&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ inputs.timezone }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;TART_TIME&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ inputs.start_time }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ND_TIME&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ inputs.end_time }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;heckout code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ctions&#x2F;checkout@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;et up Python&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ctions&#x2F;setup-python@v5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;          p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ython-version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3.12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;          c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ache&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nstall dependencies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          python -m pip install --upgrade pip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          pip install uv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;un game check&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          echo &amp;quot;Checking for games from $START_TIME to $END_TIME&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          uv run finder.py \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --lat &amp;quot;$LATITUDE&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --lng &amp;quot;$LONGITUDE&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --radius &amp;quot;$RADIUS&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --sport &amp;quot;$SPORT_ID&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --timezone &amp;quot;$TIMEZONE&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --start-time &amp;quot;$START_TIME&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --end-time &amp;quot;$END_TIME&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            --telegram&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;          T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ELEGRAM_BOT_TOKEN&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ secrets.TELEGRAM_BOT_TOKEN }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;          T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ELEGRAM_CHAT_ID&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ secrets.TELEGRAM_CHAT_ID }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I used GitHub Actions inputs to configure the variables for my script. Found this feature to be quite neat for scheduling different crons for weekday&#x2F;weekends.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;badminton_gh.png&quot; alt=&quot;alt text&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For small quality-of-life improvements - solving your own specific problems with custom scripts tailored exactly to your needs - gotta love the LLMs man. We’re gonna see more and more of such “personal tooling” in future as the entry to barrier for coding is lowered with LLMs. The democratization of coding through LLMs means people (even non-technical ones) can focus on “describing” the problem well, rather than struggling with implementation details. Being able to articulate what you want clearly becomes the primary skill - yes, it’s a skill issue if you can’t prompt well, but it’s far more accessible than learning programming from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Cleaning up Notes with LLM</title>
        <published>2025-01-03T10:15:00+05:30</published>
        <updated>2025-01-03T10:15:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/cleanup-obsidian/"/>
        <id>https://mrkaran.dev/posts/cleanup-obsidian/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/cleanup-obsidian/">&lt;p&gt;My Obsidian vault has gotten quite messy over time. I’ve been dumping notes without proper frontmatter, tags were all over the place, and some notes didn’t even have proper titles! I needed a way to clean this up without spending hours manually organizing everything.&lt;&#x2F;p&gt;
&lt;p&gt;I’d been playing around with Claude’s API lately, and thought – hey, why not use an LLM to analyze my notes and add proper frontmatter? After all, that’s what these AI models are good at – understanding context and categorizing stuff.&lt;&#x2F;p&gt;
&lt;p&gt;I wrote a small Python script using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;llm.datasette.io&#x2F;en&#x2F;stable&#x2F;&quot;&gt;llm&lt;&#x2F;a&gt; library (which is pretty neat btw) to do just this. Here’s what it looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; llm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; yaml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; datetime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; pathlib&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; re&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; ObsidianNoteProcessor&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; notes_dir&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; model_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;claude-3.5-sonnet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;notes_dir&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Path&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;notes_dir&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;model&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; llm&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;model_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; extract_existing_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Extract existing frontmatter if present.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        frontmatter_pattern&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);font-weight: bold;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*?&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);font-weight: bold;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);font-weight: bold;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        match&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; re&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;match&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;frontmatter_pattern&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; content&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; re&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;DOTALL&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; match&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span&gt; yaml&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;safe_load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;match&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; content&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;match&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            except&lt;&#x2F;span&gt;&lt;span&gt; yaml&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;YAMLError&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; generate_prompt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Generate a prompt for the LLM to analyze the note content.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Analyze the following note content and extract&#x2F;infer the following properties:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1. A clear title (if not present, generate from content)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2. Relevant categories based on the content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3. Appropriate tags (include &amp;#39;inbox&amp;#39; if content seems draft-like)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4. Status (Draft&#x2F;In Progress&#x2F;Complete) based on content completeness&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5. Priority (Low&#x2F;Medium&#x2F;High) based on content importance&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6. A brief description summarizing the content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Note content:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Return ONLY the YAML frontmatter without any code block markers. Use this exact format (omit fields if not applicable):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;title: &amp;lt;title&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;category: &amp;lt;category&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;tags:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  - tag1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  - tag2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;status: &amp;lt;status&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;priority: &amp;lt;priority&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;description: &amp;lt;description&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; clean_llm_response&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; response_text&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Clean up the LLM response to ensure proper YAML.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Remove yaml code block markers if present&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        response_text&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; response_text&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; response_text&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;startswith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;```yaml&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            response_text&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; response_text&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; response_text&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;endswith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;```&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            response_text&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; response_text&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rsplit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; response_text&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; process_note&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; file_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Process a single note file.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; encoding&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;utf-8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Extract existing frontmatter and content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            existing_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; main_content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;extract_existing_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Generate and execute prompt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            response&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;model&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;prompt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;generate_prompt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;main_content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            response_text&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clean_llm_response&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;response&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                new_frontmatter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; yaml&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;safe_load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;response_text&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; isinstance&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;new_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; dict&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;                    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Warning: Invalid response format for &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    new_frontmatter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            except&lt;&#x2F;span&gt;&lt;span&gt; yaml&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;YAMLError&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;                print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;YAML parsing error for &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;                print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Response text was:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;response_text&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                raise&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Merge with existing frontmatter, preferring existing values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            merged_frontmatter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;new_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; **&lt;&#x2F;span&gt;&lt;span&gt;existing_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add date if not present&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; merged_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                merged_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; datetime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;date&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;today&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;isoformat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Generate new note content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            new_content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            new_content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; yaml&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;dump&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;merged_frontmatter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; sort_keys&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; allow_unicode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            new_content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            new_content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; main_content&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Write back to file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; encoding&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;utf-8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                f&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;new_content&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;            print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;✓ Processed: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        except&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;            print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;✗ Error processing &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; process_vault&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Process all markdown files in the vault.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Starting Obsidian vault cleanup...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; file_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;notes_dir&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;glob&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;**&#x2F;*.md&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;process_note&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Vault cleanup completed!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Set up the model key if not already configured&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    model&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; llm&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;claude-3.5-sonnet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; hasattr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;model&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        api_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ANTHROPIC_API_KEY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; api_key&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; ValueError&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Please set ANTHROPIC_API_KEY environment variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        model&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; api_key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Initialize and run the processor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    notes_dir&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;Users&#x2F;karan&#x2F;Notes&#x2F;Obsidian&#x2F;The Wall&#x2F;Notes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    processor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ObsidianNoteProcessor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;notes_dir&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    processor&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;process_vault&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;obsd-cleanup.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The script is pretty straightforward – it reads each markdown file, extracts any existing frontmatter (because I don’t want to lose that!), and then asks Claude to analyze the content and generate appropriate frontmatter. It adds stuff like title, category, tags, status, priority.&lt;&#x2F;p&gt;
&lt;p&gt;What I love about this approach is that it’s &lt;em&gt;contextual&lt;&#x2F;em&gt;. Unlike regex-based approaches or keyword matching, the LLM actually understands what the note is about and can categorize it properly. A note about “Setting up BTRFS on Arch” automatically gets tagged with “linux”, “filesystem”, “arch” without me having to maintain a predefined list of tags. The categorization is probably better than what I’d have done manually at 2 AM while organizing my notes!&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>2024: A Year In Review</title>
        <published>2024-12-23T12:00:00+05:30</published>
        <updated>2024-12-23T12:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/2024/"/>
        <id>https://mrkaran.dev/posts/2024/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/2024/">&lt;p&gt;2024 was indeed an important year for me as it marked several significant milestones. Quite happy with how this year was! Here’s
my reflection on this memorable year.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;life&quot;&gt;Life&lt;a class=&quot;zola-anchor&quot; href=&quot;#life&quot; aria-label=&quot;Anchor link for: life&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Got married to the prettiest and dearest Saumya 💗&lt;&#x2F;li&gt;
&lt;li&gt;Did my first international trip, exploring Europe&lt;&#x2F;li&gt;
&lt;li&gt;Bought a fun toy - Maruti Jimny 4x4&lt;&#x2F;li&gt;
&lt;li&gt;Relocated to Bangalore after working from home for 4+ years since Covid&lt;&#x2F;li&gt;
&lt;li&gt;Attended several amazing concerts:
&lt;ul&gt;
&lt;li&gt;Indian Ocean&lt;&#x2F;li&gt;
&lt;li&gt;Parvaaz&lt;&#x2F;li&gt;
&lt;li&gt;Blackstratblues&lt;&#x2F;li&gt;
&lt;li&gt;Anand Bhaskar Collective&lt;&#x2F;li&gt;
&lt;li&gt;Bandland&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;travel&quot;&gt;Travel&lt;a class=&quot;zola-anchor&quot; href=&quot;#travel&quot; aria-label=&quot;Anchor link for: travel&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Switzerland&lt;&#x2F;li&gt;
&lt;li&gt;Italy&lt;&#x2F;li&gt;
&lt;li&gt;Austria&lt;&#x2F;li&gt;
&lt;li&gt;Binsar&lt;&#x2F;li&gt;
&lt;li&gt;Cochin&lt;&#x2F;li&gt;
&lt;li&gt;Ajmer&lt;&#x2F;li&gt;
&lt;li&gt;Ranthambore&lt;&#x2F;li&gt;
&lt;li&gt;Pondicherry&lt;&#x2F;li&gt;
&lt;li&gt;Chennai&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;projects&quot;&gt;Projects&lt;a class=&quot;zola-anchor&quot; href=&quot;#projects&quot; aria-label=&quot;Anchor link for: projects&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Released v1.0.0 of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doggo.mrkaran.dev&#x2F;docs&#x2F;&quot;&gt;Doggo&lt;&#x2F;a&gt; - It hit frontpage of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=40847699&quot;&gt;HN&lt;&#x2F;a&gt; as well!&lt;&#x2F;li&gt;
&lt;li&gt;Built an expense tracker app - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;gullak&quot;&gt;Gullak&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Made a lot of small utility apps:
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;lil&quot;&gt;lil&lt;&#x2F;a&gt; - URL shortener&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;silencer&quot;&gt;silencer&lt;&#x2F;a&gt; - Prometheus alerts &amp;lt;&amp;gt; Mattermost bridge&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;toru&quot;&gt;toru&lt;&#x2F;a&gt; - Go modules proxy with caching&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;junbi&quot;&gt;junbi&lt;&#x2F;a&gt; - Server Setup and Hardening Tool&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;chocolates.ovenlydelights.shop&#x2F;&quot;&gt;Ovenly Delights&lt;&#x2F;a&gt; - Small bakery shop website&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;nomcfg&quot;&gt;nomcfg&lt;&#x2F;a&gt; - Nomad config generator&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;clx&quot;&gt;clx&lt;&#x2F;a&gt; - Generate CLI commands using AI for common ops&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Started working on a log analytics app - full focus on that in 2025. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bsky.app&#x2F;profile&#x2F;mrkaran.bsky.social&#x2F;post&#x2F;3ldo7vzglnk2o&quot;&gt;Read more&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This year has been truly transformative, bringing together personal joy, professional growth, and exciting adventures. Looking forward to what 2025 has in store!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How I use LLMs</title>
        <published>2024-10-30T00:00:00+00:00</published>
        <updated>2024-10-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/using-llm/"/>
        <id>https://mrkaran.dev/posts/using-llm/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/using-llm/">&lt;p&gt;Just yesterday, GitHub &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.blog&#x2F;news-insights&#x2F;product-news&#x2F;bringing-developer-choice-to-copilot&#x2F;&quot;&gt;announced&lt;&#x2F;a&gt; integrating Claude 3.5 Sonnet with Copilot. Interesting times ahead. In my experience, Claude has been remarkably better than the GPT-4 family of models for programming tasks. I’ve tried a bunch of tools like Cursor, Continue.dev but finally settled with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aider.chat&#x2F;&quot;&gt;Aider&lt;&#x2F;a&gt; for most of my tasks. In this post, I want to write about my workflow of using Aider when working on small coding tasks.&lt;&#x2F;p&gt;
&lt;p&gt;Aider is an open source Python CLI which supports multiple models, including Claude 3.5 Sonnet. Aider describes itself as “AI pair programming in your terminal”. The tool integrates &lt;code&gt;git&lt;&#x2F;code&gt; quite well in its workflow so it can edit files, create new files, and track all changes via git. In case you want to revert, simply reverting the commit or using the &lt;code&gt;&#x2F;undo&lt;&#x2F;code&gt; shortcut would do the same.&lt;&#x2F;p&gt;
&lt;p&gt;The tool has multiple modes that serve different purposes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;ask&lt;&#x2F;code&gt;: Use it when you simply want to chat with the model about the codebase or explain some pieces of it. This mode won’t touch your files. It’s great for understanding existing code or getting explanations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;architect&lt;&#x2F;code&gt;: Use it to discuss a broad overall idea. The model will propose some changes to your files. You can further chat and tune it to your preferences.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;code&lt;&#x2F;code&gt;: This will directly edit your files and commit them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;My typical workflow involves running Aider in a terminal while keeping VSCode open for manual code review. I often use the &lt;code&gt;--no-auto-commits&lt;&#x2F;code&gt; flag to view the diffs before committing. Despite advances in LLM technology, I believe they haven’t yet reached the stage where they can fully understand your team’s coding style guides, and I prefer not to have a certain style forced upon me. Manually tweaking portions of AI-generated functions still proves helpful and saves considerable time.&lt;&#x2F;p&gt;
&lt;p&gt;To begin, &lt;code&gt;aider --sonnet&lt;&#x2F;code&gt; would open the interactive window where you can begin writing prompts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;aider-4.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To add context, you need to add files using commands like &lt;code&gt;&#x2F;add main.py&lt;&#x2F;code&gt;. What makes Aider powerful is its control over the LLM context - you can &lt;code&gt;&#x2F;add&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;drop&lt;&#x2F;code&gt; source code, or even &lt;code&gt;&#x2F;reset&lt;&#x2F;code&gt; to drop all files and start with a fresh context. This granular control helps manage the context window effectively.&lt;&#x2F;p&gt;
&lt;p&gt;A really cool thing about it is that it gives an approximate idea of the number of tokens (cost) associated with each prompt. I find it useful to remove unnecessary files from the context window, which not only helps in getting sharper, more accurate responses but also helps with the costs. There’s a nice &lt;code&gt;&#x2F;tokens&lt;&#x2F;code&gt; command which will show the cost of sending each file added in context with the prompt.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;aider-3.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I find the Aider + Claude 3.5 combo works really well when you have a narrow-scoped, well-defined task. For example, this is the prompt I used on a codebase I was working on:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Theme preference is not preserved when reloading pages or navigating to new pages. We should store this setting in localStorage. Please implement using standard best practices.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;aider-1.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Under the hood, Aider uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aider.chat&#x2F;2023&#x2F;10&#x2F;22&#x2F;repomap.html&quot;&gt;tree-sitter&lt;&#x2F;a&gt; to improve code generation and provide rich context about your codebase. Tree-sitter parses your code into an Abstract Syntax Tree (AST), which helps Aider understand the structure and relationships in your code. Unlike simpler tools that might just grep through your codebase, tree-sitter understands the actual syntax of your programming language.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It can identify function definitions, class declarations, variable scopes, and their relationships&lt;&#x2F;li&gt;
&lt;li&gt;It extracts full function signatures and type information&lt;&#x2F;li&gt;
&lt;li&gt;It builds a dependency graph showing how different parts of your code relate to each other&lt;&#x2F;li&gt;
&lt;li&gt;It helps rank the importance of different code sections based on how often they’re referenced&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This means when you’re working on a task, Aider isn’t just blindly sending your entire codebase to the LLM. Instead, it creates an optimized “repository map” that fits within your token budget (default is 1k tokens, adjustable via &lt;code&gt;--map-tokens&lt;&#x2F;code&gt;). This map focuses on the most relevant pieces of your code, making sure the LLM understands the context without wasting tokens.&lt;&#x2F;p&gt;
&lt;p&gt;Aider’s approach to AI pair programming feels natural and productive. Here are some example prompts where it helped me build stuff in less than a minute:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Modify fetch method in store&#x2F;store.go to filter out expired entries&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Write a k6 load test script to benchmark the &lt;code&gt;POST &#x2F;submit&lt;&#x2F;code&gt; endpoint and simulate real-world traffic patterns&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Create a Makefile, Dockerfile, goreleaser.yml for my Go binary. Target platforms: arm64 and amd64&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;aider-2.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I prefer to invoke &lt;code&gt;aider&lt;&#x2F;code&gt; with a few extra flags:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aider&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-no-auto-commits&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-cache-prompts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-cache-keepalive-pings&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-no-suggest-shell-commands&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make sure to go through the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aider.chat&#x2F;docs&#x2F;usage&#x2F;tips.html&quot;&gt;Tips&lt;&#x2F;a&gt; page to effectively try out Aider on your existing projects.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Self Hosting Outline Wiki</title>
        <published>2024-09-20T00:00:00+00:00</published>
        <updated>2024-09-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/setting-outline/"/>
        <id>https://mrkaran.dev/posts/setting-outline/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/setting-outline/">&lt;p&gt;I recently discovered &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getoutline.com&#x2F;&quot;&gt;Outline&lt;&#x2F;a&gt; a collaborative knowledge base. I wanted to self-host it on my server, but the mandatory auth provider requirement was off-putting. My server is on a private encrypted network (Tailscale) that only my approved devices in the tailnet can access, so I don’t really need authentication for my personal single-use apps. I found a few guides using Authelia&#x2F;Keycloak, but these are heavy-duty applications that would consume a lot of resources (DBs, caches, proxies, and whatnot) just to have an OIDC provider for Outline.&lt;&#x2F;p&gt;
&lt;p&gt;There had to be a simpler way, right? Enter &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dexidp&#x2F;dex&quot;&gt;Dex&lt;&#x2F;a&gt;. As recommended by my friend and colleague &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;maych.in&#x2F;&quot;&gt;Chinmay&lt;&#x2F;a&gt;, it turned out to be quite easy.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the full &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; setup you need to get Outline up and running on your local instance!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;utline&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ocker.getoutline.com&#x2F;outlinewiki&#x2F;outline:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nv_file&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;docker.env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3000:3000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;torage-data:&#x2F;var&#x2F;lib&#x2F;outline&#x2F;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;epends_on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ostgres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;edis&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;GSSLMODE&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;isable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;edis&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;edis&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nv_file&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;docker.env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6379:6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ealthcheck&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;est&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;CMD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis-cli&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nterval&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;imeout&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etries&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ostgres&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ostgres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nv_file&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;docker.env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5432:5432&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;atabase-data:&#x2F;var&#x2F;lib&#x2F;postgresql&#x2F;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ealthcheck&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;est&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;CMD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pg_isready&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;outline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-U&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nterval&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;imeout&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etries&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;OSTGRES_USER&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;OSTGRES_PASSWORD&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pass&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;OSTGRES_DB&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;outline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ex&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;exidp&#x2F;dex:v2.35.3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5556:5556&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;dex:&#x2F;etc&#x2F;dex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dex&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;serve&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;etc&#x2F;dex&#x2F;config.yaml&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;torage-data&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;atabase-data&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You’ll need to add the following env variables as well&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NODE_ENV&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SECRET_KEY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;y&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;UTILS_SECRET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;y&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DATABASE_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PGSSLMODE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;REDIS_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;URL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FILE_STORAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FILE_STORAGE_LOCAL_ROOT_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FILE_STORAGE_UPLOAD_MAX_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_CLIENT_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_CLIENT_SECRET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_AUTH_URI&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_TOKEN_URI&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_USERINFO_URI&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_USERNAME_CLAIM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_DISPLAY_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OIDC_SCOPES&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; profile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; email&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FORCE_HTTPS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENABLE_UPDATES&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WEB_CONCURRENCY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DEBUG&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LOG_LEVEL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally, to configure Dex, we need the following config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ssuer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ttp:&#x2F;&#x2F;localhost:5556&#x2F;dex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;torage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;qlite3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;onfig&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;var&#x2F;dex&#x2F;dex.db&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;eb&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ttp&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.0.0.0:5556&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;taticClients&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;utline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;edirectURIs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;http:&#x2F;&#x2F;localhost:3000&#x2F;auth&#x2F;oidc.callback&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Outline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ecret&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;utline-secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;auth2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;kipApprovalScreen&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nablePasswordDB&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;taticPasswords&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mail&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;admin@example.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;sername&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;serID&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;08a8684b-db88-4b73-90a9-3cd1661f5466&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Voilà! With &lt;code&gt;docker compose up&lt;&#x2F;code&gt;, you’ll have an Outline server ready to go. You can log in using the &lt;code&gt;admin&lt;&#x2F;code&gt; user.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;outline-0.png&quot; alt=&quot;image.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;outline-1.png&quot; alt=&quot;image.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Building an expense tracker app</title>
        <published>2024-06-14T00:00:00+00:00</published>
        <updated>2024-06-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/gullak/"/>
        <id>https://mrkaran.dev/posts/gullak/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/gullak/">&lt;p&gt;A couple of weeks ago, I decided to start logging and tracking my expenses. The goal was not to record every minor purchase but to gain a general insight into where my money was going. In this post, I’ll dive deep into the behind-the-scenes of building &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;gullak&quot;&gt;Gullak&lt;&#x2F;a&gt;—an expense tracker app with a dash of &lt;em&gt;AI&lt;&#x2F;em&gt; (yes).&lt;&#x2F;p&gt;
&lt;div style=&quot;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&quot;&gt;
  &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;29wLnPMbsE8?si=O_GStAkPGZ09oywE&quot; 
          style=&quot;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&quot; 
          title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; 
          allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; 
          referrerpolicy=&quot;strict-origin-when-cross-origin&quot; 
          allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;gullak-cover.png&quot; alt=&quot;Gullak&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why&lt;a class=&quot;zola-anchor&quot; href=&quot;#why&quot; aria-label=&quot;Anchor link for: why&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My wife and I have a simple system for tracking our expenses during trips: we use Apple Notes to maintain a day-wise record, jotting down a one-liner for each expense under the date. This straightforward method has proven effective in keeping tabs on our spending habits while traveling.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;images&#x2F;gullak-1.png&quot; style=&quot;max-width:100%; height:auto; width:400px;&quot;&gt;
&lt;p&gt;For instance, during our last Europe trip, we recorded our daily expenses. After returning home, I was eager to analyze our spending patterns. I copied all these items into Google Sheets to analyse the top categories that I spent on during the trip.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;gullak-2.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I decided to develop a simple expense tracker app that automatically categorizes expenses into various groups like food, travel, shopping, etc. I believed this was a practical use case for leveraging an LLM paired with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;platform.openai.com&#x2F;docs&#x2F;guides&#x2F;function-calling&quot;&gt;Function calling&lt;&#x2F;a&gt; to parse and categorize expenses.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;initial-prototype&quot;&gt;Initial Prototype&lt;a class=&quot;zola-anchor&quot; href=&quot;#initial-prototype&quot; aria-label=&quot;Anchor link for: initial-prototype&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first step involved designing a prompt to capture user input about their spending. I picked up &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sashabaranov&#x2F;go-openai&quot;&gt;go-openai&lt;&#x2F;a&gt; library and experimented with it.&lt;&#x2F;p&gt;
&lt;p&gt;Almost a year ago, I had developed a small bot for personal use, which provided a JSON output detailing the macronutrients and calories in specific food items, storing this information in Metabase. However, this was during the early days of API access provided by OpenAI. Due to occasionally unsatisfactory and inconsistent responses (despite instructions like “MUST RETURN JSON OR 1000 CATS WILL D*E SOMEWHERE”), it wasn’t entirely reliable.&lt;&#x2F;p&gt;
&lt;p&gt;Function calling addresses two main limitations of traditional language model responses:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inconsistent response format&lt;&#x2F;strong&gt;: Without function calling, responses from language models can be unstructured and inconsistent, requiring complex validation and parsing logic on the application side.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lack of external data integration&lt;&#x2F;strong&gt;: Language models are typically limited to the knowledge they were trained on, making it challenging to provide answers based on real-time or external data.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It’s important to note that the LLM does not actually &lt;em&gt;execute&lt;&#x2F;em&gt; any functions. Rather, we create a structure for the LLM to follow in its responses. The LLM would then generate a response with the content as a stringified JSON object following the schema provided in the function definiton.&lt;&#x2F;p&gt;
&lt;p&gt;I created a function called &lt;code&gt;categorize_expense&lt;&#x2F;code&gt;. This function takes a list of transactions as parameters, with each transaction having properties like &lt;code&gt;transaction_date&lt;&#x2F;code&gt;, &lt;code&gt;amount&lt;&#x2F;code&gt;, &lt;code&gt;category&lt;&#x2F;code&gt;, and &lt;code&gt;description&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s what this looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fnCategorizeExpenses&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; openai&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;FunctionDefinition&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;categorize_expense&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Description&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Categorize expenses from the given input.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Parameters&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Type&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Object&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Properties&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;transactions&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        Type&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;        jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        Description&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;List of items purchased&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        Items&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Type&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Object&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Properties&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;transaction_date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Type&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;        jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Description&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Date of transaction in ISO 8601 format (e.g., 2021-09-01) if specified else today&amp;#39;s date.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Type&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;        jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Number&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Description&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount of the item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;category&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Type&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;        jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Description&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;One word category of the expense (e.g., food, travel, entertainment)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Type&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;        jsonschema&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Description&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Concise and short description of the item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Required&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;transaction_date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;category&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Required&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;transactions&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The response from this API call can then be unmarshalled into a struct.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;var&lt;&#x2F;span&gt;&lt;span&gt; transactions&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; models&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Transactions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; json&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Unmarshal&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;toolCall&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Function&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Arguments&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;transactions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The next step was to determine exactly how users would provide input. I considered various methods that would make entering expenses as straightforward as my approach with Apple Notes and decided to create a Telegram bot.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;gullak-3.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I developed a Telegram bot that would parse the expenses and save them to a SQLite database. I explored tools like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;evidence.dev&#x2F;&quot;&gt;evidence.dev&lt;&#x2F;a&gt;, a nice platform for creating frontends using the database as the sole source of truth. However, I encountered an issue where it could not correctly parse date values (see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;evidence-dev&#x2F;evidence&#x2F;issues&#x2F;1983&quot;&gt;GitHub issue&lt;&#x2F;a&gt;). Ultimately, I returned to my reliable old friend—Metabase.&lt;&#x2F;p&gt;
&lt;p&gt;However, I faced two main challenges with this approach:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Privacy Concerns&lt;&#x2F;strong&gt;: Telegram does not offer the option to create a private bot; all bots generated through BotFather are public. To restrict access, I considered adding session tokens, but this approach was unsatisfactory. If I planned to distribute this bot, implementing a token-based, DIY authentication system on Telegram did not seem appropriate.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fixing Bad Entries&lt;&#x2F;strong&gt;: To correct erroneous entries, I had to manually update the SQLite table. As I intended to share this bot with my wife, I needed a more user-friendly workflow. Manually raw dogging &lt;code&gt;UPDATE&lt;&#x2F;code&gt; SQL queries was not the most user-friendly solution.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After a day or two of experimenting, I decided to build a small frontend for now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-frontend&quot;&gt;Building Frontend&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-frontend&quot; aria-label=&quot;Anchor link for: building-frontend&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;gullak-home.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As a backend developer, my core expertise is NOT JavaScript, and I strongly dislike the JS ecosystem. Obviously there’s no dearth of choices when it comes to frameworks, however for this project I wanted to stay away from the hype and choose a stack that is simple to use and productive (for me) out of the box. Having used Vue.js in production in the past, I feel it ticks those boxes for me as it comes bundled with a router, store, and all the niceties, and it has &lt;strong&gt;excellent&lt;&#x2F;strong&gt; documentation. After reading a refresher on the new Vue3 composition API syntax, I hit the ground running.&lt;&#x2F;p&gt;
&lt;p&gt;I find Tailwind CSS ideal for someone like me who prefers not to write CSS or invent class names. It’s a heavily debated topic online, but it’s important to pick our battles. An issue I encountered while researching UI frameworks was that Vue.js seems to have fewer options compared to React, likely due to its lower popularity. After some google-fu, I discovered a promising project called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shadcn-vue.com&#x2F;&quot;&gt;shadcn-vue&lt;&#x2F;a&gt;, an unofficial community led port of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ui.shadcn.com&#x2F;&quot;&gt;shadcn&#x2F;ui&lt;&#x2F;a&gt; React library.&lt;&#x2F;p&gt;
&lt;p&gt;The cool thing about this library is that it doesn’t come bundled as a package, meaning there’s no way to install it as a &lt;em&gt;dependency&lt;&#x2F;em&gt;. Instead, it gets added directly to your source code, encouraging you to tweak it the way you like.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;images&#x2F;gullak-4.png&quot;  height=&quot;400&quot;&gt;
&lt;p&gt;I believe it’s an excellent starting point for anyone looking to build their own design system from scratch, as it allows for customization of both appearance and behavior. It might have been overkill for my simple UI, but I thought, what the heck, if side projects aren’t for exploring new things, what’s the point of it all? 😄&lt;&#x2F;p&gt;
&lt;h2 id=&quot;database&quot;&gt;Database&lt;a class=&quot;zola-anchor&quot; href=&quot;#database&quot; aria-label=&quot;Anchor link for: database&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For the database, I opted for SQLite. It’s perfect for a small project like this since the database is just a single file, making it easier to manage. Initially, I used the popular driver &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mattn&#x2F;go-sqlite3&quot;&gt;mattn&#x2F;go-sqlite3&lt;&#x2F;a&gt;, but I found that the CGO-free alternative &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;modernc.org&#x2F;sqlite&quot;&gt;modernc&#x2F;sqlite&lt;&#x2F;a&gt; works just as well.&lt;&#x2F;p&gt;
&lt;p&gt;I also experimented with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sqlc.dev&#x2F;&quot;&gt;sqlc&lt;&#x2F;a&gt; for the first time. For those unfamiliar, &lt;code&gt;sqlc&lt;&#x2F;code&gt; generates type-safe Go code from your raw SQL queries. It handles all the boilerplate database code needed to retrieve results, scan them into a model, manage transactions, and more. sqlc makes it seem like you’re getting the best of both worlds (ORM + raw SQL).&lt;&#x2F;p&gt;
&lt;p&gt;Here’s an example query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; name: CreateTransaction :many&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Inserts a new transaction into the database.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span&gt; transactions (created_at, transaction_date, amount, currency, category, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;description&lt;&#x2F;span&gt;&lt;span&gt;, confirm)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;VALUES&lt;&#x2F;span&gt;&lt;span&gt; (?, ?, ?, ?, ?, ?, ?)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;RETURNING &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using &lt;code&gt;sqlc generate&lt;&#x2F;code&gt;, it generates the following code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Code generated by sqlc. DO NOT EDIT.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; versions:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;   sqlc v1.26.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; source: queries.sql&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;package&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; db&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;database&#x2F;sql&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; createTransaction&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-- name: CreateTransaction :many&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;INSERT INTO transactions (created_at, transaction_date, amount, currency, category, description, confirm)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;VALUES (?, ?, ?, ?, ?, ?, ?)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;RETURNING id, created_at, transaction_date, currency, amount, category, description, confirm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; CreateTransactionParams&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	CreatedAt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;       time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json:&amp;quot;created_at&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	TransactionDate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json:&amp;quot;transaction_date&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Amount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;          float64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json:&amp;quot;amount&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Currency&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        string&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json:&amp;quot;currency&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Category&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        string&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json:&amp;quot;category&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     string&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json:&amp;quot;description&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Confirm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;         bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json:&amp;quot;confirm&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Inserts a new transaction into the database.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;q &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Queries&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; CreateTransaction&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; arg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; CreateTransactionParams&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Transaction&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	rows&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;query&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;ctx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;createTransactionStmt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; createTransaction&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		arg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;CreatedAt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		arg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;TransactionDate&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		arg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Amount&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		arg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Currency&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		arg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Category&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		arg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Description&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		arg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Confirm&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	defer&lt;&#x2F;span&gt;&lt;span&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Transaction&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		var&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Transaction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ID&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;CreatedAt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;TransactionDate&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Currency&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Amount&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Category&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Description&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Confirm&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;items&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; rows&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span&gt; items&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;apple-shortcuts&quot;&gt;Apple Shortcuts&lt;a class=&quot;zola-anchor&quot; href=&quot;#apple-shortcuts&quot; aria-label=&quot;Anchor link for: apple-shortcuts&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Similar to my Apple Notes approach, I wanted to create a shortcut that would allow me to log expenses quickly. I created a simple shortcut that would prompt me to enter the expenses and send an HTTP POST request to Gullak’s API server. I then open the dashboard once in a while to confirm&#x2F;edit these unconfirmed transactions.&lt;&#x2F;p&gt;
&lt;p&gt;You can read more about setting up the Shortcut in your Apple devices &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;gullak?tab=readme-ov-file#apple-shortcut-integration&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;proudly-not-a-weekend-project&quot;&gt;Proudly, Not a Weekend Project&lt;a class=&quot;zola-anchor&quot; href=&quot;#proudly-not-a-weekend-project&quot; aria-label=&quot;Anchor link for: proudly-not-a-weekend-project&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For every “I could do this in a weekend” comment, yes, this project is straightforward—a “CRUD GPT” wrapper that isn’t complicated to build. Yet, it took me over a month to develop. I spent less than an hour most days on this project, instead of cramming it into an all-nighter weekend project - an approach I want to move away from. Slow and steady efforts compound, outlasting quick, sporadic bursts. I’m pleased to balance this with my full-time job without burning out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ideas-for-the-future&quot;&gt;Ideas for the Future&lt;a class=&quot;zola-anchor&quot; href=&quot;#ideas-for-the-future&quot; aria-label=&quot;Anchor link for: ideas-for-the-future&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Initially, I didn’t set out to build a comprehensive budgeting app, just an expense logger, as that was my primary need. However, if usage increases and the tool proves helpful in reducing unnecessary spending, I’m open to adding more features. Some possibilities include a subscription tracker, integration with budgeting tools like YNAB or Actual through their APIs, and monthly reports sent via email. The best part is that you own complete data, as the data is stored locally on your device so you can also export it anytime and build other integrations on top of it.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to open a GitHub issue or &lt;a href=&quot;&#x2F;contact&#x2F;&quot;&gt;reach out&lt;&#x2F;a&gt; if you have any suggestions or feedback. I’m excited to see where this project goes!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update-feb-2026&quot;&gt;Update (Feb 2026)&lt;a class=&quot;zola-anchor&quot; href=&quot;#update-feb-2026&quot; aria-label=&quot;Anchor link for: update-feb-2026&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve rewritten Gullak to use plain-text ledger files. Read more about why in the follow-up post: &lt;a href=&quot;&#x2F;posts&#x2F;gullak-ledger&#x2F;&quot;&gt;Why Plain-Text Ledger is Powerful for Gullak&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Random Act of Kindness</title>
        <published>2024-04-21T00:00:00+00:00</published>
        <updated>2024-04-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/random-kind-stranger/"/>
        <id>https://mrkaran.dev/posts/random-kind-stranger/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/random-kind-stranger/">&lt;p&gt;Last month, I did a wonderful trip travelling through the scenic landscapes of Switzerland. My wife and I were in Lucerne and had scheduled a day trip to Mt. Titlis for the next day but were wondering what to do that evening. After strolling along the Chapel Bridge and enjoying an amazing lunch by the waterfront, my wife and I collectively decided to book a Lake Lucerne cruise for the evening. It seemed like the perfect setup for a romantic date night, or so I thought!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;lucerne.jpeg&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We got the tickets from the information booth for the evening and went back to our hotel to freshen up and relax for a bit.&lt;&#x2F;p&gt;
&lt;p&gt;We arrived exactly at 6:45 PM, as mentioned on our tickets, and started to wait. Except, there were only the two of us waiting. We waited for probably half an hour, until 7:15 PM, which was the departure time. Knowing how precise the Swiss transport system usually is, I sensed something fishy. Luckily, I spotted Martin, a staff member of the cruise company, and asked him about it. He looked puzzled by my question and informed me that there was no cruise scheduled for today. Yep, not today, not tomorrow, and not for the rest of the weekend. It was Easter time, and all the cruise trips were cancelled. In fact, he was quite as puzzled as I was as to how the lady at the ticket counter even gave us the tickets for today. However, he told me that he couldn’t do much and suggested writing an email for a refund. I was a bit sad as this dashed our evening plans, but I thought, fine… Shit happens. It’s not the end of the world!&lt;&#x2F;p&gt;
&lt;p&gt;And then, out of nowhere, by pure serendipity, my wife spotted another member of the cruise—this time, in fact, the captain! She began to tell the captain about our ordeal. The captain, a very warm and kind lady, listened to my wife patiently and understood our plight! She apologized on behalf of her company and immediately offered a refund in cash for the tickets that we had purchased. We were quite happy, as following up on emails, etc., was something that I was not particularly excited about looking forward to during the other half of my trip. So we said yes, except she needed to go to the ATM to draw cash. We waited for her and chatted with Martin about random stuff! He told us some really fun stories about how &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.theguardian.com&#x2F;world&#x2F;2023&#x2F;mar&#x2F;05&#x2F;matterhorn-mountain-toblerone-packaging-design-switzerland&quot;&gt;Toblerone’s iconic packaging no longer features the Matterhorn mountain&lt;&#x2F;a&gt;. He also shared practical advice on how to safeguard oneself against pickpockets in Italy(we were gonna visit it soon), and reminisced about his life in Zermatt before relocating to Lucerne.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, the wait stretched longer than usual, and I found myself wondering about her whereabouts. And then finally, we saw her approaching us. She told us that she hadn’t found a working ATM nearby, and had to go a bit far. But she didn’t come back empty-handed; she also brought us macaroons as a token of her apologies, a gesture that was incredibly thoughtful. She handed us 200 CHF in cash, covering more than the 180 CHF we had paid for our tickets. When we attempted to return the excess 20 CHF, she firmly refused to take it back. Despite our insistence on returning the excess 20 CHF, she remained steadfast, refusing to accept it. She encouraged us to use the extra money to enjoy a few drinks, suggesting it as a consolation for our evening plans being spoiled by the canceled cruise.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;lucerne-kind-cash.jpeg&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I am glad the cruise didn’t happen. Life has its own ways of revealing that kindness exists in every corner of the world, and serendipity can lead to the most memorable encounters! For most, it may not be a huge thing, but for me, it was a profoundly touching and generous act from a stranger who simply chose to be kind without any ulterior motives.&lt;&#x2F;p&gt;
&lt;p&gt;The lesson: Be kind to others, do no harm, and always pay it forward. :)&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Travelling with Tailscale</title>
        <published>2024-03-27T00:00:00+00:00</published>
        <updated>2024-03-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/travel-tailscale/"/>
        <id>https://mrkaran.dev/posts/travel-tailscale/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/travel-tailscale/">&lt;p&gt;I have an upcoming trip to Europe, which I am quite excited about. I wanted to set up a Tailscale exit node to ensure that critical apps I depend on, such as banking portals continue working from outside the country. Tailscale provides a feature called “Exit nodes”. These nodes can be setup to route all traffic (0.0.0.0&#x2F;0, ::&#x2F;0) through them.&lt;&#x2F;p&gt;
&lt;p&gt;I deployed a tiny DigitalOcean droplet in &lt;code&gt;BLR&lt;&#x2F;code&gt; region and setup Tailscale as an exit node. The steps are quite simple and can be found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;kb&#x2F;1103&#x2F;exit-nodes&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;net.ipv4.ip_forward = 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tee&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;sysctl.d&#x2F;99-tailscale.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;net.ipv6.conf.all.forwarding = 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tee&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;sysctl.d&#x2F;99-tailscale.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sysctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;sysctl.d&#x2F;99-tailscale.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; up&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-advertise-exit-node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The node is now advertised as an exit node, and we can confirm that from the output of &lt;code&gt;tailscale status&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; status&lt;&#x2F;span&gt;&lt;span&gt;                       &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.78.212.33&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   pop-os&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               mr-karan@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    linux&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.75.180.88&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   homelab&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;              mr-karan@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    linux&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.100.191.57&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  iphone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               mr-karan@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    iOS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     offline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.123.189.14&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  karans-macbook-pro&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   mr-karan@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    macOS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   offline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.104.67.7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    lab&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                  mr-karan@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    linux&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   offline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.108.220.87&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  tailscale-exit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       mr-karan@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    linux&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   active&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; exit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; direct&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 167.71.236.222:41641,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 21540&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 17356&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On the client side, I was able to start Tailscale and configure it to send all the traffic to the exit node with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; up&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-exit-node=100.108.220.87&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can confirm that the traffic is going via the exit node by checking our public IP from this device:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;➜&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  https:&#x2F;&#x2F;ipinfo.io&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;167.x.x.222&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;city&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Doddaballapura&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;region&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Karnataka&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;country&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;loc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;13.2257,77.5750&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;org&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;AS14061 DigitalOcean, LLC&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;postal&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;560100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;timezone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Asia&#x2F;Kolkata&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;readme&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;ipinfo.io&#x2F;missingauth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;                            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, I encountered a minor issue since I needed to bring my work laptop for on-call duties, in case any critical production incidents required my attention during my travels. At my organization, we use Netbird as our VPN, which, like Tailscale, creates a P2P overlay network between different devices.&lt;&#x2F;p&gt;
&lt;p&gt;The problem was that all 0.0.0.0 traffic was routed to the exit node, meaning the internal traffic meant for Netbird to access internal sites on our private AWS VPC network was no longer routed via the Netbird interface.&lt;&#x2F;p&gt;
&lt;p&gt;Netbird automatically propagates a bunch of IP routing rules when connected to the system. These routes are to our internal AWS VPC infrastructure. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10.0.0.0&#x2F;16&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; via&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100.107.12.215&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wt0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, &lt;code&gt;wt0&lt;&#x2F;code&gt; is the Netbird interface. So, for example, any IP like &lt;code&gt;10.0.1.100&lt;&#x2F;code&gt; will go via this interface. To verify this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; route&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.0.1.100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10.0.1.100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wt0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100.107.12.215&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; uid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, after connecting to the Tailscale exit node, this was no longer the case. Now, even the private IP meant to be routed via Netbird was being routed through Tailscale:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; route&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.0.1.100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10.0.1.100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; table&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 52&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100.78.212.33&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; uid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Although Tailscale nodes allow for the selective whitelisting of CIDRs to route only the designated network packets through them, my scenario was different. I needed to selectively bypass certain CIDRs and route all other traffic through the exit nodes. I came across a relevant &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tailscale&#x2F;tailscale&#x2F;issues&#x2F;1916&quot;&gt;GitHub issue&lt;&#x2F;a&gt;, but unfortunately, it was closed due to limited demand.&lt;&#x2F;p&gt;
&lt;p&gt;This led me to dig deeper into understanding how Tailscale propagates IP routes, to see if there was a way for me to add custom routes with a higher priority.&lt;&#x2F;p&gt;
&lt;p&gt;Initially, I examined the IP routes for Tailscale. Typically, one can view the route table list using &lt;code&gt;ip route&lt;&#x2F;code&gt;, which displays the routes in the &lt;code&gt;default&lt;&#x2F;code&gt; and &lt;code&gt;main&lt;&#x2F;code&gt; tables. However, Tailscale uses routing table 52 for its routes, instead of the default or main table.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; route&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; show&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; table&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 52&lt;&#x2F;span&gt;&lt;span&gt;                                                           &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale0&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.75.180.88&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale0&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; others&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;throw&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 127.0.0.0&#x2F;8&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;192.168.29.0&#x2F;24&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale0&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A few notes on the route table:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;default dev tailscale0&lt;&#x2F;code&gt; is the default route for this table. Traffic that doesn’t match any other route in this table will be sent through the &lt;code&gt;tailscale0&lt;&#x2F;code&gt; interface. This ensures that any traffic not destined for a more specific route will go through the Tailscale network.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;throw 127.0.0.0&#x2F;8&lt;&#x2F;code&gt;: This is a special route that tells the system to “throw” away traffic destined for 127.0.0.0&#x2F;8 (local host addresses) if it arrives at this table, effectively discarding it before it reaches the local routing table.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We can see the priority of these IP rules are evaluated using &lt;code&gt;ip rule show&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;➜&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rule&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; show&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;0:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5210:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fwmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0x80000&#x2F;0xff0000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5230:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fwmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0x80000&#x2F;0xff0000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5250:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fwmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0x80000&#x2F;0xff0000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; unreachable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5270:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 52&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;32766:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;32767:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This command lists all the current policy routing rules, including their priority (look for the pref or priority value). Each rule is associated with a priority, with lower numbers having higher priority.&lt;&#x2F;p&gt;
&lt;p&gt;By default, Linux uses three main routing tables:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Local (priority 0)&lt;&#x2F;li&gt;
&lt;li&gt;Main (priority 32766)&lt;&#x2F;li&gt;
&lt;li&gt;Default (priority 32767)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Since Netbird already propagates the IP routes in the main routing table, we only need to add a higher priority rule to lookup in the &lt;code&gt;main&lt;&#x2F;code&gt; table before Tailscale takes over.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rule&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; add&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.0.0.0&#x2F;16&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pref&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, our &lt;code&gt;ip rule&lt;&#x2F;code&gt; looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rule&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; show&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;0:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.0.0.0&#x2F;16&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5210:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fwmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0x80000&#x2F;0xff0000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5230:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fwmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0x80000&#x2F;0xff0000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5250:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fwmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0x80000&#x2F;0xff0000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; unreachable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5270:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 52&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;32766:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;32767:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To confirm whether the packets for destination &lt;code&gt;10.0.0.0&#x2F;16&lt;&#x2F;code&gt; get routed via &lt;code&gt;wt0&lt;&#x2F;code&gt; instead of &lt;code&gt;tailscale0&lt;&#x2F;code&gt;, we can use the good ol’ &lt;code&gt;ip route get&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; route&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.0.1.100&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10.0.1.100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wt0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100.107.12.215&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; uid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! This setup allows us to route all our public traffic via exit node and only the internal traffic meant for internal AWS VPCs get routed via Netbird VPN.&lt;&#x2F;p&gt;
&lt;p&gt;Since, these rules are ephemeral and I wanted to add a bunch of similar network routes, I created a small shell script to automate the process of adding&#x2F;deleting rules:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Function to add IP rules for specified CIDRs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Adding IP rules...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rule&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; add&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.0.0.0&#x2F;16&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pref&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ... others ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Function to remove IP rules based on preference numbers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Removing IP rules...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rule&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; del&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pref&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ... others ....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Check the first argument to determine which function to call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        add&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        remove&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Invalid argument: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Usage: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; add|remove&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;esac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>One Billion Row Challenge in Go</title>
        <published>2024-01-10T00:00:00+00:00</published>
        <updated>2024-01-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/1brc/"/>
        <id>https://mrkaran.dev/posts/1brc/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/1brc/">&lt;p&gt;Earlier this week, I had stumbled upon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gunnarmorling&#x2F;1brc&quot;&gt;1brc&lt;&#x2F;a&gt;, which presents a fun task: loading a huge text file (1 billion lines) in Java as quickly as possible.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The One Billion Row Challenge (1BRC) is a fun exploration of how far modern Java can be pushed for aggregating one billion rows from a text file. Utilize all your virtual threads, leverage SIMD, optimize your GC, or employ any other technique to create the fastest implementation for this task!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The challenge is mainly about Java, but I thought to do the same in my preferred language: Go. This post is about how I did several iterations to my Go program to reduce the time and discuss the main techniques used in each iteration to make it faster.&lt;&#x2F;p&gt;
&lt;p&gt;I was able to create a solution which takes &lt;strong&gt;~20s&lt;&#x2F;strong&gt; to read, parse and calculate stats for 1bn lines on my Apple M2 (10 vCPU, 32GB RAM).
There are some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gunnarmorling&#x2F;1brc&#x2F;discussions&#x2F;138&quot;&gt;insane&lt;&#x2F;a&gt; solutions that people have come up with, be sure to check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gunnarmorling&#x2F;1brc&#x2F;discussions&quot;&gt;GitHub Discussions&lt;&#x2F;a&gt; to go through them!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;a class=&quot;zola-anchor&quot; href=&quot;#prerequisites&quot; aria-label=&quot;Anchor link for: prerequisites&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To generate the text file for these measurements, follow the steps outlined &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gunnarmorling&#x2F;1brc?tab=readme-ov-file#prerequisites&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After running the commands, I have a &lt;code&gt;measurements.txt&lt;&#x2F;code&gt; on my file system:&lt;&#x2F;p&gt;
&lt;p&gt;Example output after running the commands:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;➜&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  1brc-go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; git:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; du&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; measurements.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; 13G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	measurements.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;➜&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  1brc-go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; git:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tail&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; measurements.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Mek&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ele;13.3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Kampala;50.8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Dikson;-3.7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Dodoma;20.3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;San Diego;7.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Chihuahua;20.3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Ngaoundéré;24.2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Toronto;12.7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Wrocław;12.6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Singapore;14.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;ultra-minimalistic-example-of-reading-a-file&quot;&gt;Ultra minimalistic example of reading a file&lt;a class=&quot;zola-anchor&quot; href=&quot;#ultra-minimalistic-example-of-reading-a-file&quot; aria-label=&quot;Anchor link for: ultra-minimalistic-example-of-reading-a-file&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s take a look at a basic Go code to read and parse the above file. We’ll also calculate stats on the fly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;package&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;bufio&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;os&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sort&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;strconv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;strings&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Measurement&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Station&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Temp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    float64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Mean&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Max&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Open the file.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	file&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;measurements.txt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;		panic&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	defer&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Map to hold the temperatures for each station.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	stationTemps&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;float64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	scanner&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; bufio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewScanner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Parse each line into a Measurement struct.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		parts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strings&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		temp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strconv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;ParseFloat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stationTemps&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stationTemps&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Calculate min, mean, and max for each station.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	results&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temps&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; stationTemps&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; max&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; temps&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temps&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; temps&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; min&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; max&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				max&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;temps&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		results&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Stats&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Mean&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; mean&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Max&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; max&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Sort the stations and format the output.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span&gt; stations&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; results&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stations&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stations&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	sort&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Strings&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stations&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; stations&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; results&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%.1f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%.1f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%.1f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stations&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On running the above program, we get the following output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{Chihuahua=20.3&#x2F;20.3&#x2F;20.3, Dikson=-3.7&#x2F;-3.7&#x2F;-3.7, Dodoma=20.3&#x2F;20.3&#x2F;20.3, Kampala=50.8&#x2F;50.8&#x2F;50.8, Mek&amp;#39;ele=13.3&#x2F;13.3&#x2F;13.3, Ngaoundéré=24.2&#x2F;24.2&#x2F;24.2, San Diego=7.1&#x2F;7.1&#x2F;7.1, Singapore=14.4&#x2F;14.4&#x2F;14.4, Toronto=12.7&#x2F;12.7&#x2F;12.7, Wrocław=12.6&#x2F;12.6&#x2F;12.6}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This approach works well for small, simple files. However, there are certain restrictions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It reads the file line by line using a scanner. Reading and processing a billion rows is time-consuming.&lt;&#x2F;li&gt;
&lt;li&gt;Each operation, even if small, adds up when repeated a billion times. This includes string splitting, type conversion, error checking, and appending to a slice.&lt;&#x2F;li&gt;
&lt;li&gt;Additionally, we need to consider the potential of hitting the max Disk IOPS limit if we perform too many file operations per second.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Before we proceed to optimize this further, let’s establish a baseline performance of &lt;em&gt;100 million&lt;&#x2F;em&gt; lines first:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ &lt;&#x2F;span&gt;&lt;span&gt;wc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt;l&lt;&#x2F;span&gt;&lt;span&gt; measurements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  100000000&lt;&#x2F;span&gt;&lt;span&gt; measurements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ &lt;&#x2F;span&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; go&lt;&#x2F;span&gt;&lt;span&gt; run&lt;&#x2F;span&gt;&lt;span&gt; main&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  go&lt;&#x2F;span&gt;&lt;span&gt; run&lt;&#x2F;span&gt;&lt;span&gt; main&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt;  18.44s&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt; 0.83s&lt;&#x2F;span&gt;&lt;span&gt; system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt; cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 19&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;135&lt;&#x2F;span&gt;&lt;span&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Baseline: It takes approximately 19s to read and calculate stats from 100 mn lines.&lt;&#x2F;p&gt;
&lt;p&gt;There’s a lot of room to optimize it further, let’s go through them one by one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iteration-1-producer-consumer-pattern&quot;&gt;Iteration 1: Producer-Consumer Pattern&lt;a class=&quot;zola-anchor&quot; href=&quot;#iteration-1-producer-consumer-pattern&quot; aria-label=&quot;Anchor link for: iteration-1-producer-consumer-pattern&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The concept involves reading multiple lines simultaneously in the producer Goroutine and then dispatching these batches to worker Goroutines. We can establish a worker pool to implement a producer-consumer pattern. Producers read lines from the file and send them to a channel. Consumers retrieve lines from the channel, parse the data, and calculate the minimum, mean, and maximum temperatures for each station.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	numWorkers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; runtime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NumCPU&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	runtime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;GOMAXPROCS&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;numWorkers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	linesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1000000&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	resultsChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; numWorkers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Start worker goroutines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span&gt; wg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; numWorkers&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;linesChan&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resultsChan&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;wg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Read the file and send lines to the workers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		file&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;measurementsFile&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;			panic&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		defer&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		scanner&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; bufio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewScanner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			linesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;		close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;linesChan&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Collect results from workers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;	close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resultsChan&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Aggregate results&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	finalResults&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; workerResult&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; resultsChan&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; workerResult&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			finalStats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; finalResults&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; max&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			finalResults&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; finalStats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Print results&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;	printStats&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalResults&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;linesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; resultsChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	defer&lt;&#x2F;span&gt;&lt;span&gt; wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	stationStats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; linesChan&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		parts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strings&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;line&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		temp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strconv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;ParseFloat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; stationStats&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; max&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;temp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stationStats&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;parts&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	resultsChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; stationStats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; max&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; printStats&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;statsMap&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span&gt; stations&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; statsMap&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stations&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stations&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	sort&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Strings&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stations&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; stations&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; statsMap&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%.1f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%.1f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%.1f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stations&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;results&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results&quot; aria-label=&quot;Anchor link for: results&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The concurrent version, unexpectedly, resulted in almost a 3x decrease in performance.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span&gt; run&lt;&#x2F;span&gt;&lt;span&gt; main&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt;  84.15s&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt; 101.34s&lt;&#x2F;span&gt;&lt;span&gt; system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 342&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt; cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 54&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;225&lt;&#x2F;span&gt;&lt;span&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where did we go wrong? This is a classic case where the overhead of concurrency mechanisms outweighs their benefits. In our current implementation, each line is sent to the channel individually, which is likely less efficient than batching lines for processing. This means that for a file with a large number of lines, there will be an equally large number of channel send operations. Each channel operation involves locking and unlocking, which can be costly, especially in a high-frequency context.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iteration-2-batch-processing-of-lines&quot;&gt;Iteration 2: Batch processing of lines&lt;a class=&quot;zola-anchor&quot; href=&quot;#iteration-2-batch-processing-of-lines&quot; aria-label=&quot;Anchor link for: iteration-2-batch-processing-of-lines&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In this version we are Batching the lines before sending to the worker which will significantly reduce the overhead of channel communication.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Batch Processing&lt;&#x2F;strong&gt;: Each batch contains &lt;strong&gt;&lt;code&gt;batchSize&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; lines. This reduces the frequency of channel operations (both sending and receiving), as well as the overhead associated with these operations.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Efficient Worker Utilization&lt;&#x2F;strong&gt;: With batch processing, each worker goroutine spends more time processing data and less time interacting with channels. This reduces the overhead of context switching and synchronization, making the processing more efficient.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	batchSize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1000000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Number of lines per batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		scanner&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; bufio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewScanner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		var&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span&gt; batchSize&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				batchesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Start a new batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Send any remaining lines in the last batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			batchesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;		close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batchesChan&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;batchesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; resultsChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	defer&lt;&#x2F;span&gt;&lt;span&gt; wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	stationStats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; batchesChan&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Process the line ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	resultsChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; stationStats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;results-1&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results-1&quot; aria-label=&quot;Anchor link for: results-1&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The improvement from iteration 2 to iteration 3 is quite remarkable, thanks to efficiently batching the lines together and reducing the number of channel ops.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main.go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  30.02s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0.67s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 476%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6.442&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So far, we’ve reduced the time to about 6.5s which is a great start and improvement of our baseline version of 19s. However, we’re making quite a few extra memory allocations and the focus of next iteration should be to reduce that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iteration-3-reducing-memory-allocations&quot;&gt;Iteration 3: Reducing memory allocations&lt;a class=&quot;zola-anchor&quot; href=&quot;#iteration-3-reducing-memory-allocations&quot; aria-label=&quot;Anchor link for: iteration-3-reducing-memory-allocations&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;A batch slice is pre-allocated with a capacity of &lt;strong&gt;&lt;code&gt;batchSize&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; and reused for each batch of lines.&lt;&#x2F;li&gt;
&lt;li&gt;After sending a batch to the channel, the slice is reset to zero length (&lt;code&gt;batch = batch[:0]&lt;&#x2F;code&gt;), but the underlying array is retained and reused.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Read the file and send batches of lines to the workers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		file&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;measurementsFile&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;			panic&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		defer&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		scanner&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; bufio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewScanner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; batchSize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Pre-allocate with capacity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;			&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Reuse the batch slice by appending to it until it reaches the batch size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span&gt; batchSize&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				batchesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Reset the slice without allocating new memory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Send any remaining lines in the last batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			batchesChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;		close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batchesChan&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;results-2&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results-2&quot; aria-label=&quot;Anchor link for: results-2&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Down to 5.3s!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main.go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  25.43s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0.53s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 485%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5.346&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;iteration-3-cont-further-reducing-memory-allocations&quot;&gt;Iteration 3 (cont): Further reducing memory allocations&lt;a class=&quot;zola-anchor&quot; href=&quot;#iteration-3-cont-further-reducing-memory-allocations&quot; aria-label=&quot;Anchor link for: iteration-3-cont-further-reducing-memory-allocations&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Avoiding &lt;code&gt;strings.Split&lt;&#x2F;code&gt;: Instead of using &lt;code&gt;strings.Split&lt;&#x2F;code&gt;, which allocates a new slice for each line, we can use  &lt;code&gt;strings.Index&lt;&#x2F;code&gt; to find the delimiter and manually slice the string. &lt;code&gt;strings.Split&lt;&#x2F;code&gt; typically creates a new slice for each split part, leading to more memory usage and subsequent GC overhead.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; batchesChan&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			delimiterIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strings&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Index&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;line&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span&gt; delimiterIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				continue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Delimiter not found, skip this line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			station&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;delimiterIndex&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			tempStr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;delimiterIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			temp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strconv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;ParseFloat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tempStr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				continue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Invalid temperature value, skip this line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; stationStats&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; max&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;temp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			stationStats&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;results-3&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results-3&quot; aria-label=&quot;Anchor link for: results-3&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The time has further decreased from 5.3s to 4.8s with these changes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span&gt; run&lt;&#x2F;span&gt;&lt;span&gt; main&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt;  15.69s&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);font-style: italic;&quot;&gt; 0.44s&lt;&#x2F;span&gt;&lt;span&gt; system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 332&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt; cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;853&lt;&#x2F;span&gt;&lt;span&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;iteration-4-read-file-in-chunks&quot;&gt;Iteration 4: Read file in chunks&lt;a class=&quot;zola-anchor&quot; href=&quot;#iteration-4-read-file-in-chunks&quot; aria-label=&quot;Anchor link for: iteration-4-read-file-in-chunks&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In this version, the file is read in chunks, and each chunk is processed to ensure it contains complete lines. The &lt;code&gt;processChunk&lt;&#x2F;code&gt; function is used to separate valid data from leftover data in each chunk. Chunk size can be controlled with command line args as well.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; chunkSize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 256&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1024&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; 256 KB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chunkSize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	leftover&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chunkSize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			bytesRead&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span&gt; bytesRead&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;				&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Copy the chunk to a new slice, because the&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;				&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; buffer will be reused in the next iteration.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				chunk&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; bytesRead&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;				copy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; buf&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;bytesRead&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;				&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Process the chunk. The returned leftover will be processed in the next iteration.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				validChunk&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; newLeftover&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; processChunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; leftover&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				leftover&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; newLeftover&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;				&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Send the valid chunk to the processing goroutine.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;validChunk&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;					wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;					go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; processChunkData&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;validChunk&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resultsChan&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;wg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				break&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;		close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resultsChan&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; processChunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; leftover&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;validChunk&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; newLeftover&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	firstNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	lastNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Find the first and last newline in the chunk.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; chunk&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span&gt; firstNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				firstNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			lastNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; firstNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		validChunk&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;leftover&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chunk&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;lastNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		newLeftover&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;lastNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;		copy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;newLeftover&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chunk&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;lastNewline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		newLeftover&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;leftover&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chunk&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span&gt; validChunk&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; newLeftover&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; processChunkData&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; resultsChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	defer&lt;&#x2F;span&gt;&lt;span&gt; wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	stationStats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	scanner&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; bufio&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewScanner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;strings&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewReader&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; scanner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Find the index of the delimiter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		delimiterIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strings&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Index&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;line&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; delimiterIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			continue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Delimiter not found, skip this line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Extract the station name and temperature string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		station&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;delimiterIndex&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		tempStr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;delimiterIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Convert the temperature string to a float&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		temp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; strconv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;ParseFloat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tempStr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			continue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Invalid temperature value, skip this line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Update the statistics for the station&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; exists&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; stationStats&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;exists&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Stats&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Max&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; max&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; temp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;temp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		stationStats&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Send the computed stats to resultsChan&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	resultsChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; stationStats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In addition to this, I moved the &lt;code&gt;aggregateStats&lt;&#x2F;code&gt; to a separate Goroutine as well:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	aggWg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	finalResults&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stats&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Start a separate goroutine for aggregation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		defer&lt;&#x2F;span&gt;&lt;span&gt; aggWg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; workerResult&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; resultsChan&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			for&lt;&#x2F;span&gt;&lt;span&gt; station&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; workerResult&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				finalStats&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; exists&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; finalResults&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;exists&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;					finalResults&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;					continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Min&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; max&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				totalCount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;totalCount&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				finalStats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; totalCount&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				finalResults&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;station&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; finalStats&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;results-4&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results-4&quot; aria-label=&quot;Anchor link for: results-4&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We’re down from 4.8s to just 2.1s to read&#x2F;parse&#x2F;process 100mn lines!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;.&#x2F;bin&#x2F;1brc.bin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-file=input.txt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-chunksize=1048576&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  17.58s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0.77s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; system&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 837%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2.190&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Basic File Reading and Parsing (Baseline)&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;&#x2F;strong&gt;: 19s (baseline).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Key Change&lt;&#x2F;strong&gt;: Sequentially reading and processing each line.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Speedup&lt;&#x2F;strong&gt;: N&#x2F;A (baseline).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Producer-Consumer Pattern&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;&#x2F;strong&gt;: 54.225s.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Key Change&lt;&#x2F;strong&gt;: Implemented concurrent line processing with producer-consumer pattern.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Speedup&lt;&#x2F;strong&gt;: -185% (slower than baseline).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Batch Processing of Lines&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;&#x2F;strong&gt;: 6.442s.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Key Change&lt;&#x2F;strong&gt;: Batched lines before processing, reducing channel communication.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Speedup&lt;&#x2F;strong&gt;: +66% (compared to baseline).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reducing Memory Allocations - Iteration 1&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;&#x2F;strong&gt;: 5.346s.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Key Change&lt;&#x2F;strong&gt;: Reused batch slices and reduced memory allocations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Speedup&lt;&#x2F;strong&gt;: +72% (compared to baseline).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reducing Memory Allocations - Iteration 2 (Avoiding &lt;code&gt;strings.Split&lt;&#x2F;code&gt;)&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;&#x2F;strong&gt;: 4.853s.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Key Change&lt;&#x2F;strong&gt;: Replaced &lt;code&gt;strings.Split&lt;&#x2F;code&gt; with manual slicing for efficiency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Speedup&lt;&#x2F;strong&gt;: +75% (compared to baseline).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Read File in Chunks&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;&#x2F;strong&gt;: 2.190s.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Key Change&lt;&#x2F;strong&gt;: Processed file in chunks and optimized aggregation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Speedup&lt;&#x2F;strong&gt;: +87% (compared to baseline).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;final-run&quot;&gt;Final Run&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-run&quot; aria-label=&quot;Anchor link for: final-run&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’m quite satisfied with the final version for now. We can now proceed to test it with 1 billion lines. However it’s evidently CPU-bound, as we spawn N workers for N CPUs.&lt;&#x2F;p&gt;
&lt;p&gt;I experimented with different chunk sizes, and here are the results from each run:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Chunk Size&lt;&#x2F;th&gt;&lt;th&gt;Time&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;512.00 KB&lt;&#x2F;td&gt;&lt;td&gt;23.756s&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;1.00 MB&lt;&#x2F;td&gt;&lt;td&gt;21.798s&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;16.00 MB&lt;&#x2F;td&gt;&lt;td&gt;20.693s&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;32.00 MB&lt;&#x2F;td&gt;&lt;td&gt;19.501s&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Tweaking the chunk size doesn’t significantly impact performance, as processing larger chunks takes longer.&lt;&#x2F;p&gt;
&lt;p&gt;TL;DR: On an average and with multiple runs it takes approx &lt;strong&gt;20s&lt;&#x2F;strong&gt; with the final iteration for 1bn lines.&lt;&#x2F;p&gt;
&lt;p&gt;Checkout the full code on my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;1brc-go&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;potential-improvements&quot;&gt;Potential Improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#potential-improvements&quot; aria-label=&quot;Anchor link for: potential-improvements&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This project was not only fun but also a great opportunity to revisit and refine many Go concepts. There are several ideas to contemplate for further improving this version’s timings:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I haven’t yet considered using &lt;code&gt;mmap&lt;&#x2F;code&gt;, but I believe it could substantially speed things up.&lt;&#x2F;li&gt;
&lt;li&gt;To delve even deeper, custom line parsing functions, especially for converting &lt;code&gt;string&lt;&#x2F;code&gt; to &lt;code&gt;float64&lt;&#x2F;code&gt;, could offer improvements.&lt;&#x2F;li&gt;
&lt;li&gt;Employing custom hashing functions (perhaps FnV) might aid in faster map lookups.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Making sad servers happy</title>
        <published>2023-11-06T00:00:00+00:00</published>
        <updated>2023-11-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/sad-servers/"/>
        <id>https://mrkaran.dev/posts/sad-servers/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/sad-servers/">&lt;h2 id=&quot;introduction-to-sadservers&quot;&gt;Introduction to SadServers&lt;a class=&quot;zola-anchor&quot; href=&quot;#introduction-to-sadservers&quot; aria-label=&quot;Anchor link for: introduction-to-sadservers&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Recently, I stumbled upon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sadservers.com&quot;&gt;sadservers&lt;&#x2F;a&gt;, a platform described as “Like LeetCode for Linux”. The premise is: you are given access to a full remote Linux server with a pre-configured problem. Your mission is to diagnose and fix the issues in a fixed time window.&lt;&#x2F;p&gt;
&lt;p&gt;With the goal of documenting my journey through these challenges and sharing the knowledge gained, I decided to not only tackle these puzzles but also to record my solutions in a video format. The format is twofold in its purpose: it allows me to reflect on my problem-solving approach and provides a resource for others who may encounter similar problems, whether in real-world scenarios or in preparation for an SRE&#x2F;DevOps interview.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-learning-curve&quot;&gt;The Learning Curve&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-learning-curve&quot; aria-label=&quot;Anchor link for: the-learning-curve&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Each server presented a different issue, from misconfigured network settings to services failing to start, from permission issues to resource overutilization. One server, for instance, had a failing database service because of a disk full partition. The cause? Stale backup files. Another had a web server throwing errors because of incorrect file permissions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recording-the-solutions&quot;&gt;Recording the Solutions&lt;a class=&quot;zola-anchor&quot; href=&quot;#recording-the-solutions&quot; aria-label=&quot;Anchor link for: recording-the-solutions&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The video recordings start with an introduction to the problem and my initial thoughts. Viewers can see my screen as I work through the issue, making the troubleshooting process transparent and educational. The commentary explains my thought process, the tools&#x2F;CLI utilities used, and the solutions applied.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;part-1&quot;&gt;Part 1&lt;a class=&quot;zola-anchor&quot; href=&quot;#part-1&quot; aria-label=&quot;Anchor link for: part-1&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;vdR8-ubkpRU?si=GGusRmnqk8bqKoCW&quot; title=&quot;Making sad servers happy - Part 1&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;h3 id=&quot;part-2&quot;&gt;Part 2&lt;a class=&quot;zola-anchor&quot; href=&quot;#part-2&quot; aria-label=&quot;Anchor link for: part-2&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;b-VFnaX78xY?si=Ql0zvph3p-U5wzwE&quot; title=&quot;Making sad servers happy - Part 2&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;h3 id=&quot;part-3&quot;&gt;Part 3&lt;a class=&quot;zola-anchor&quot; href=&quot;#part-3&quot; aria-label=&quot;Anchor link for: part-3&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;-42S4xcim8Y?si=n1s7KHyZluyf4TLc&quot; title=&quot;Making sad servers happy - Part 3&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For those looking to enhance their Linux troubleshooting skills, sadservers.com is a gold mine. It’s an excellent preparation ground for anyone aiming to step into the SRE&#x2F;DevOps field or wanting to keep their skills sharp.&lt;&#x2F;p&gt;
&lt;p&gt;As I continue to record and share these troubleshooting escapades, I invite you to subscribe, comment with your insights, or even suggest what types of challenges you’d like to see addressed next.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Nomad can do everything that K8s can</title>
        <published>2023-07-23T05:34:47+00:00</published>
        <updated>2023-07-23T05:34:47+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/nomad-k8s-showdown/"/>
        <id>https://mrkaran.dev/posts/nomad-k8s-showdown/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/nomad-k8s-showdown/">&lt;p&gt;This blog post is ignited by the following &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ibuildthecloud&#x2F;status&#x2F;1682800502738931712&quot;&gt;Twitter exchange&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad-k8s-showdown-1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don’t take the accusation of &lt;em&gt;unsubstantiated&lt;&#x2F;em&gt; argument, especially on a technical topic lightly. I firmly believe in substantiated arguments and hence, here I am, elaborating on my stance. If found mistaken, I am open to corrections and revise my stance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;some-historical-context&quot;&gt;Some Historical Context&lt;a class=&quot;zola-anchor&quot; href=&quot;#some-historical-context&quot; aria-label=&quot;Anchor link for: some-historical-context&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;In my professional capacity, I have run and managed several K8s clusters (using AWS EKS) for our entire team of devs (&lt;em&gt;been there done that&lt;&#x2F;em&gt;). The most complex piece of our otherwise simple and clean stack was K8s and we’d been longing to find a better replacement. None of us knew whether that would be Nomad or anything else. But we took the chance and we have reached a stage where we can objectively argue that, for our specific workloads, Nomad has proven to be a superior tool compared to K8s.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-with-nomad&quot;&gt;Building with Nomad&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-with-nomad&quot; aria-label=&quot;Anchor link for: building-with-nomad&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Nomad presents a fundamental building block approach to designing your own services. It used to be true that Nomad was primarily a scheduler, and for serious production workloads, you had to rely on Consul for service discovery and Vault for secret management. However, this scenario has changed as Nomad now seamlessly integrates these features, making them first-class citizens in its environment. Our team replaced our HashiCorp stack with just Nomad, and we never felt constrained in terms of what we could accomplish with Consul&#x2F;Vault. While these tools still hold relevance for larger clusters managed by numerous teams, they are not necessary for our use case.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deconstructing-infrastructure&quot;&gt;Deconstructing Infrastructure&lt;a class=&quot;zola-anchor&quot; href=&quot;#deconstructing-infrastructure&quot; aria-label=&quot;Anchor link for: deconstructing-infrastructure&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Kubernetes employs a declarative state for every operation in the cluster, essentially operating as a reconciliation mechanism to keep everything in check. In contrast, Nomad requires dealing with fewer components, making it appear lacking compared to K8s’s concept of everything being a “resource.” However, that is far from the truth.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ingress&lt;&#x2F;strong&gt;: We run a set of HAProxy on a few nodes which act as “L7 LBs”. Configured with Nomad services, they can do the routing based on Host headers.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;DNS&lt;&#x2F;strong&gt;: To provide external access to a service without using a proxy, we developed a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;nomad-external-dns&quot;&gt;tool&lt;&#x2F;a&gt; that scans all services registered in the cluster and creates a corresponding DNS record on AWS Route53.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Monitoring&lt;&#x2F;strong&gt;: Ah my fav. You wanna monitor your K8s cluster. Sure, here’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;prometheus-operator&#x2F;kube-prometheus&quot;&gt;kube-prometheus&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;prometheus-operator&#x2F;prometheus-operator&quot;&gt;prometheus-operator&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;kube-state-metrics&quot;&gt;kube-state-metrics&lt;&#x2F;a&gt;. Choices, choices. Enough to confuse you for days. Anyone who’s ever deployed any of these, tell me why this thing needs such a monstrosity setup of CRDs and operators. Monitoring Nomad is such a breeze, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.hashicorp.com&#x2F;nomad&#x2F;docs&#x2F;configuration&#x2F;telemetry&quot;&gt;3 lines of HCL&lt;&#x2F;a&gt; config and done.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Statefulsets&lt;&#x2F;strong&gt;: It’s 2023 and the irony is rich - the recommended way to run a database inside K8s is… not to run it inside K8s at all. In Nomad, we run a bunch of EC2 instances and tag them as &lt;code&gt;db&lt;&#x2F;code&gt; nodes. The DBs don’t float around as containers to random nodes. And there’s no CSI plugin reaching for a storage disk in AZ-1 when the node is basking in AZ-2. Running a DB on Nomad feels refreshingly like running it on an unadorned EC2 instance.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Autoscale&lt;&#x2F;strong&gt;: All our client nodes (except for the &lt;code&gt;db&lt;&#x2F;code&gt; nodes) are ephemeral and part of AWS’s Auto Scaling Groups (ASGs). We use ASG rules for the horizontal scaling of the cluster. While Nomad does have its own autoscale, our preference is to run large instances dedicated to specific workloads, avoiding a mix of different workloads on the same machine.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;over-abstraction-of-kubernetes&quot;&gt;Over abstraction of Kubernetes&lt;a class=&quot;zola-anchor&quot; href=&quot;#over-abstraction-of-kubernetes&quot; aria-label=&quot;Anchor link for: over-abstraction-of-kubernetes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One of my primary critiques of K8s is its hidden complexities. While these abstractions might simplify things on the surface, debugging becomes a nightmare when issues arise. Even after three years of managing K8s clusters, I’ve never felt confident dealing with databases or handling complex networking problems involving dropped packets.&lt;&#x2F;p&gt;
&lt;p&gt;You might argue that it’s about technical chops, which I won’t disagree with - but then do you want to add value to the business by getting shit done or do you want to be the resident K8s whiz at your organization?&lt;&#x2F;p&gt;
&lt;p&gt;Consider this: How many people do you know who run their own K8s clusters? Even the K8s experts themselves preach about running prod clusters on EKS&#x2F;GKE etc. How many fully leverage all that K8s has to offer? How many are even aware of all the network routing intricacies managed by kube-proxy? If these queries stir up clouds of uncertainty, it’s possible you’re sipping the Kubernetes Kool-Aid without truly comprehending the recipe, much like I found myself doing at one point&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nomad-not-perfect-but-simpler&quot;&gt;Nomad: Not Perfect, But Simpler&lt;a class=&quot;zola-anchor&quot; href=&quot;#nomad-not-perfect-but-simpler&quot; aria-label=&quot;Anchor link for: nomad-not-perfect-but-simpler&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now, if you’re under the impression that I’m singing unabashed praises for Nomad, let me clarify - Nomad has its share of challenges. I’ve personally encountered and reported several. However, the crucial difference lies in Nomad’s lesser degree of abstraction, allowing for a comprehensive understanding of its internals. For instance, we encountered &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;16762&quot;&gt;service reconciliation issues&lt;&#x2F;a&gt; with a particular Nomad version. However, we could query the APIs, identify the problem, and write a bash script to resolve and reconcile it. It wouldn’t have been possible when there are too many moving parts in the system and we don’t know where to even begin debugging.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;noyaml.com&#x2F;&quot;&gt;YAML hell&lt;&#x2F;a&gt; is all too well known to all of us. In K8s, writing job manifests required a lot of effort (by the developers who don’t work with K8s all day) and were very complex to understand. It felt “too verbose” and involved copy pasting large blocks from the docs and trying to make things work. Compare that to HCL, it feels much nicer to read and shorter. Things are more straightforward to understand.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve not even touched upon the nice-ities on Nomad yet. Like better humanly understandable ACLs? Cleaner and simpler job spec, which defines the entire job in one file? A UI which actually shows everything about your cluster, nodes, and jobs? Not restricting your workloads to be run as Docker containers? A single binary which powers all of this?&lt;&#x2F;p&gt;
&lt;p&gt;The central question this post aims to raise is: What can K8s do that Nomads can’t, especially considering the features people truly need? My perspectives are informed not only by my organization but also through interactions with several other organizations at various meetups and conferences. Yet, I have rarely encountered a use case that could only be managed by K8s. While Nomad isn’t a panacea for all issues, it’s certainly worth a try. Reducing the complexity of your tech stack can prove beneficial for your applications and, most importantly, your developers.&lt;&#x2F;p&gt;
&lt;p&gt;At this point, K8s enjoys immense industry-wide support, while Nomad remains the unassuming newcomer. This contrast is not a negative aspect, per se. Large organizations often gravitate towards complexity and the opportunity to engage more engineers. However, if simplicity were the primary goal, the prevailing sense of overwhelming complexity in the infrastructure and operations domain wouldn’t be as pervasive.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I hope my arguments provide a more comprehensive perspective and address the earlier critique of being unsubstantiated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update&quot;&gt;Update&lt;a class=&quot;zola-anchor&quot; href=&quot;#update&quot; aria-label=&quot;Anchor link for: update&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;blockquote class=&quot;admonition info&quot;&gt;
    &lt;strong class=&quot;admonition-header&quot;&gt;INFO&lt;&#x2F;strong&gt;
    &lt;p&gt;&lt;p&gt;Darren has responded to this blog post. You can read the response on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ibuildthecloud&#x2F;status&#x2F;1682992374979629057&quot;&gt;Twitter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Storing AWS Pinpoint Logs</title>
        <published>2023-07-21T05:24:06+00:00</published>
        <updated>2023-07-21T05:24:06+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/storing-aws-pinpoint-logs/"/>
        <id>https://mrkaran.dev/posts/storing-aws-pinpoint-logs/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/storing-aws-pinpoint-logs/">&lt;p&gt;At $dayjob, we use AWS Pinpoint to send out SMS to our customers. We’ve also written a detailed &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zerodha.tech&#x2F;blog&#x2F;logging-at-zerodha&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; on how we use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;&quot;&gt;Clickhouse&lt;&#x2F;a&gt; + &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;&quot;&gt;vector&lt;&#x2F;a&gt; stack for our logging needs. We additionally wanted to store the delivery logs generated by the Pinpoint service. But like with anything else in AWS, even simpler tasks like these usually tend to piggyback on other counterparts of AWS - in this case, it happens to be AWS Kinesis. All the delivery logs which contain metadata about SMS delivery are streamed to Kinesis.&lt;&#x2F;p&gt;
&lt;p&gt;Our setup involves configuring Pinpoint with Amazon Kinesis Data Firehose stream. Firehose is an ETL service that helps stream events to other persistent stores. Firehose supports multiple such output sinks and in our case we use &lt;code&gt;HTTP&lt;&#x2F;code&gt; sink.&lt;&#x2F;p&gt;
&lt;p&gt;This is what the flow looks like:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Pinpoint -&amp;gt; Kinesis Firehose -&amp;gt; Vector HTTP -&amp;gt; Clickhouse&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;ingesting-data&quot;&gt;Ingesting Data&lt;a class=&quot;zola-anchor&quot; href=&quot;#ingesting-data&quot; aria-label=&quot;Anchor link for: ingesting-data&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;On the HTTP server side, we used &lt;code&gt;vector&lt;&#x2F;code&gt;’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;configuration&#x2F;sources&#x2F;aws_kinesis_firehose&#x2F;&quot;&gt;aws_kinesis_firehose&lt;&#x2F;a&gt; source. Compared to just using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;configuration&#x2F;sources&#x2F;http_server&#x2F;&quot;&gt;http&lt;&#x2F;a&gt; source, here are the differences I found:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Has first-class support for access_key. AWS Kinesis can be configured to send access_key which comes as the value &lt;code&gt;X-Amz-Firehose-Access-Key&lt;&#x2F;code&gt; header in the HTTP request. This means that the request which contains an invalid access key will be rejected at the source itself. However, in the &lt;code&gt;http&lt;&#x2F;code&gt; source, I couldn’t find a way to drop events at the source level. It is required to use a VRL transformer to check whether &lt;code&gt;X-Amz-Firehose-Access-Key&lt;&#x2F;code&gt; is present in the headers and do a value comparison with our key.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Has native support for &lt;code&gt;base64&lt;&#x2F;code&gt; decoding the payload. This one’s pretty useful and saved me a lot of VRL transformer rules that I would have otherwise written with the &lt;code&gt;http&lt;&#x2F;code&gt; source. So, basically, this is how the server receives the payload:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;requestId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6a14a06b-6eae-4218-...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1689766125971&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;records&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eyJld...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eyJldmVudF9...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The value of the payload is a base64 encoded value of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;pinpoint&#x2F;latest&#x2F;developerguide&#x2F;event-streams-data-sms.html&quot;&gt;JSON Object&lt;&#x2F;a&gt; of an SMS event. However, the &lt;code&gt;aws_kinesis_firehose&lt;&#x2F;code&gt; source is smart enough and automagically decodes this list of records and their values into individual events. This is how the final event looks like when using &lt;code&gt;aws_kinesis_firehose&lt;&#x2F;code&gt; source:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;event_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_SMS.SUCCESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;event_timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:1689827914426,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;arrival_timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:1689827917659,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;event_version&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;application&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{}},&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;client&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;},&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;device&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;platform&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{}},&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;session&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{},&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;attributes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sender_request_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;destination_phone_number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+91xxx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;record_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;DELIVERED&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;iso_country_code&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mcc_mnc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;xxx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;number_of_message_parts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;message_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;message_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Transactional&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;origination_phone_number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redactedORG&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;},&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;metrics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;price_in_millicents_usd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:xx.0},&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;awsAccountId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;request_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6dd45388-xxx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;source_arn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;arn:aws:firehose:ap-south-1:redacted:deliverystream&#x2F;redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;source_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;aws_kinesis_firehose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2023-07-20T04:39:38.772Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This makes it straightforward because now we just have to parse the JSON inside the &lt;code&gt;message&lt;&#x2F;code&gt; key and do transformations on that object. If it was &lt;code&gt;http&lt;&#x2F;code&gt; source, then I’d to loop over the records structure and figure out how to split them as individual events for the rest of the Vector pipeline… which would have been messy to say the least.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here’s the vector config so far:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;firehose&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; General&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;aws_kinesis_firehose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;address&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;127.0.0.1:9000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;store_access_key&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;access_keys&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;superdupersecret&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Use it for debugging&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sinks&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;firehose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;format_pinpoint_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;encoding&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;codec&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;formatting-the-data&quot;&gt;Formatting the data&lt;a class=&quot;zola-anchor&quot; href=&quot;#formatting-the-data&quot; aria-label=&quot;Anchor link for: formatting-the-data&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a pipeline which sends and receives data, we can process the events and transform them into a schema that is more desirable. Since we require the events to be queryable in a Clickhouse DB, this is the schema we have:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span&gt;.pinpoint_logs (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Asia&#x2F;Kolkata&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;event_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;record_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;origination_phone_number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; String,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;message_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; String,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;destination_phone_number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; String,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;arrival_timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Asia&#x2F;Kolkata&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;event_timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Asia&#x2F;Kolkata&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;meta&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; Nullable(String)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENGINE &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; MergeTree&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;PARTITION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; BY&lt;&#x2F;span&gt;&lt;span&gt; toYYYYMM(_timestamp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; _timestamp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SETTINGS index_granularity &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 8192&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To achieve the above format, we can use VRL to parse and format our SMS events:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;transforms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;format_pinpoint_logs&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;remap&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;firehose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;source&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  # Decode the JSON message and set ingestion timestamp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .message = parse_json!(.message)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .ingestion_timestamp = .timestamp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  # Convert timestamps from Unix to DateTime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .event_timestamp = from_unix_timestamp!(.message.event_timestamp, unit:&amp;quot;milliseconds&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .arrival_timestamp = from_unix_timestamp!(.message.arrival_timestamp, unit:&amp;quot;milliseconds&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  # Extract keys to top level and remove from attributes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .record_status = del(.message.attributes.record_status)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .origination_phone_number = del(.message.attributes.origination_phone_number)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .destination_phone_number = del(.message.attributes.destination_phone_number)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .message_id = del(.message.attributes.message_id)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  # Encode the remaining attributes as JSON string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  .attr = encode_json(.message.attributes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  # Format Payload for Clickhouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  . = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;_timestamp&amp;quot;: .ingestion_timestamp,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;arrival_timestamp&amp;quot;: .arrival_timestamp,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;event_timestamp&amp;quot;: .event_timestamp,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;app_id&amp;quot;: .message.application.app_id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;event_type&amp;quot;: .message.event_type,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;record_status&amp;quot;: .record_status,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;message_id&amp;quot;: .message_id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;origination_phone_number&amp;quot;: .origination_phone_number,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;destination_phone_number&amp;quot;: .destination_phone_number,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;meta&amp;quot;: .attr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Plugging this, we have a clean JSON object for each SMS event. The only thing now we need to add is an output sink to Clickhouse:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sinks&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;clickhouse&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;format_pinpoint_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;skip_unknown_fields&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;compression&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;gzip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;database&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;http:&#x2F;&#x2F;127.0.0.1:8123&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;table&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pinpoint_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;encoding&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;timestamp_format&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;unix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;max_bytes&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1049000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; 1 MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;timeout_secs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;max_size&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 268435488&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;disk&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;when_full&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;block&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! On running this pipeline with &lt;code&gt;vector -c config.toml&lt;&#x2F;code&gt; we can see the consumption the records&lt;&#x2F;p&gt;
&lt;p&gt;Hope this short post was useful if you’ve to do anything similar!&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bridge Networking in Nomad</title>
        <published>2023-07-17T05:45:04+00:00</published>
        <updated>2023-07-17T05:45:04+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/bridge-network-in-nomad/"/>
        <id>https://mrkaran.dev/posts/bridge-network-in-nomad/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/bridge-network-in-nomad/">&lt;p&gt;To set the stage, it’s crucial to understand what we mean by “bridge networking”. In a nutshell, it is a type of network connection in Linux that allows virtual interfaces, like the ones used by virtual machines and containers, to share a physical network interface.&lt;&#x2F;p&gt;
&lt;p&gt;With Nomad, when a task is allocated, it creates a network namespace with its own network stack. Within this, a virtual ethernet (veth) pair is established, one end of which is assigned to the network namespace of the allocation, and the other remains in the host namespace.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;bridge-network-in-nomad-4.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-network-journey&quot;&gt;&lt;strong&gt;The Network Journey&lt;&#x2F;strong&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-network-journey&quot; aria-label=&quot;Anchor link for: the-network-journey&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To illustrate this practically, let’s assume a packet is sent from a task within an allocation. The packet would first be received by the local end of the veth pair, it would then traverse to the other end residing in the host’s namespace. From there, it is sent to the bridge on the host (in this case, the “nomad” bridge), which finally sends the packet out to the world via the host’s physical network interface (typically “eth0” or equivalent in your machine).&lt;&#x2F;p&gt;
&lt;p&gt;The journey of a packet from the outside world to a task inside an allocation is the exact mirror image. The packet reaches “eth0” first, then the nomad bridge, it is then forwarded to the appropriate veth interface in the host’s namespace. From there, it crosses over to the other end of the veth pair in the allocation’s network namespace and finally gets routed to the destination task.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-bridge-or-not-to&quot;&gt;To bridge or not to&lt;a class=&quot;zola-anchor&quot; href=&quot;#to-bridge-or-not-to&quot; aria-label=&quot;Anchor link for: to-bridge-or-not-to&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s take a look at the following jobspec which is for deploying my tiny side project - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;cloak&quot;&gt;Cloak&lt;&#x2F;a&gt; on Nomad&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;cloak&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  datacenters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dc1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cloak-redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      provider&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;                  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis:7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        advertise_ipv6_address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        volumes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;data&#x2F;cloak&#x2F;redis:&#x2F;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 500&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; MHz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 256&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;cloak&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;cloak&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 7000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 7000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;cloak&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ghcr.io&#x2F;mr-karan&#x2F;cloak:v0.2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--config=config.toml&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cloak&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      template&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;# Configuration for 1 redis instances, as assigned via rendezvous hashing.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{$allocID := env &amp;quot;NOMAD_ALLOC_ID&amp;quot; -}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{range nomadService 1 $allocID &amp;quot;cloak-redis&amp;quot;}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;CLOAK_REDIS__address={{ .Address }}:{{ .Port }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{- end}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        destination&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;secrets&#x2F;file.env&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        env&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;         =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 500&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; MHz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 700&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our focus should be on the &lt;code&gt;network.mode&lt;&#x2F;code&gt; stanza. To illustrate what happens behind the scenes when an alloc runs in &lt;code&gt;network.mode=host&lt;&#x2F;code&gt; (host network), we can run the above job.&lt;&#x2F;p&gt;
&lt;p&gt;On the machine, we can see that port 7000 (static) and port 27042 (dynamic) are allocated on the host network interface (eth0):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;bridge-network-in-nomad-1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can also see the port and process details using &lt;code&gt;ss&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ss&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ltpn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sport = :7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;State&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    Recv-Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Send-Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      Local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Address:Port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       Peer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Address:Port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;LISTEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 4096&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      95.216.165.210:7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    0.0.0.0:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  users:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker-proxy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,pid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This config is more suitable for specific workloads - like load balancers or similar deployments where you want to expose the network interface on the host. It’s also helpful for applications running outside of Nomad on that host to connect via the host network interface.&lt;&#x2F;p&gt;
&lt;p&gt;However, typically in a job where you want to connect to multiple different allocs - you’d want to set up a bridge network. This generally avoids exposing the workload on the host network directly. It’s a typical setup where you want to put applications behind a reverse proxy (NGINX&#x2F;Caddy).&lt;&#x2F;p&gt;
&lt;p&gt;Let’s change &lt;code&gt;network.mode=bridge&lt;&#x2F;code&gt; in the above job spec and see the changes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; plan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cloak.nomad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;+&#x2F;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Job:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cloak&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;+&#x2F;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Group:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cloak&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; (1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; create&#x2F;destroy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; update&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Network&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      Hostname:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MBits:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Mode:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bridge&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; HostNetwork:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Label:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cloak&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; To:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Value:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Network&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      Hostname:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MBits:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Mode:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; HostNetwork:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Label:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cloak&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; To:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Value:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    Task:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cloak&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;+&#x2F;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Group:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; (1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; create&#x2F;destroy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; update&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Network&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      Hostname:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MBits:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Mode:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bridge&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Dynamic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; HostNetwork:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Label:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; To:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Network&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      Hostname:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MBits:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Mode:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Dynamic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; HostNetwork:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Label:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; To:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    Task:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we don’t see the ports forwarded on the host network:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;bridge-network-in-nomad-2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, &lt;code&gt;ss&lt;&#x2F;code&gt; also shows no process listening on the host network&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;bridge-network-in-nomad-3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iptables-and-routing&quot;&gt;&lt;strong&gt;IPTables and Routing&lt;&#x2F;strong&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#iptables-and-routing&quot; aria-label=&quot;Anchor link for: iptables-and-routing&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To understand what happened when we switched the networking mode to &lt;code&gt;bridge&lt;&#x2F;code&gt;, we need to take a look at the Nomad &lt;code&gt;iptables&lt;&#x2F;code&gt; magic which comes into play when using &lt;code&gt;bridge&lt;&#x2F;code&gt; network.&lt;&#x2F;p&gt;
&lt;p&gt;I pulled up the &lt;code&gt;iptables&lt;&#x2F;code&gt; and saw specific rules under the chains &lt;code&gt;CNI-FORWARD&lt;&#x2F;code&gt; and &lt;code&gt;NOMAD-ADMIN&lt;&#x2F;code&gt;. These rules, in essence, allow all traffic to and from the allocation’s network namespace.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;L&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; CNI-FORWARD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Chain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; CNI-FORWARD&lt;&#x2F;span&gt;&lt;span&gt; (1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; references&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;target&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     prot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; source&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               destination&lt;&#x2F;span&gt;&lt;span&gt;         &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NOMAD-ADMIN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  anywhere&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;             anywhere&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;             &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; CNI&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; firewall&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; plugin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; admin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; overrides&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ACCEPT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  anywhere&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;             172.26.64.5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          ctstate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; RELATED,ESTABLISHED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ACCEPT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  172.26.64.5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          anywhere&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ACCEPT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  anywhere&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;             172.26.64.6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          ctstate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; RELATED,ESTABLISHED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ACCEPT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  172.26.64.6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          anywhere&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;L&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; NOMAD-ADMIN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Chain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; NOMAD-ADMIN&lt;&#x2F;span&gt;&lt;span&gt; (1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; references&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;target&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     prot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; source&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               destination&lt;&#x2F;span&gt;&lt;span&gt;         &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ACCEPT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  anywhere&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;             172.26.64.0&#x2F;20&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nomad uses &lt;code&gt;172.26.64.0&#x2F;20&lt;&#x2F;code&gt; as the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.hashicorp.com&#x2F;nomad&#x2F;docs&#x2F;configuration&#x2F;client#bridge_network_subnet&quot;&gt;default subnet&lt;&#x2F;a&gt; for the bridge network. The IPs &lt;code&gt;172.26.64.5&lt;&#x2F;code&gt; and &lt;code&gt;172.26.64.6&lt;&#x2F;code&gt; are assigned to 2 different allocs in this CIDR. The &lt;code&gt;iptables&lt;&#x2F;code&gt; rules allow complete traffic to flow on this subnet.&lt;&#x2F;p&gt;
&lt;p&gt;To check the routing,&lt;code&gt;ip route&lt;&#x2F;code&gt; command can be used.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; route&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; show&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.0&#x2F;20&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;172.26.64.0&#x2F;20&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; proto&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kernel&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; scope&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; link&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It uses the &lt;code&gt;nomad&lt;&#x2F;code&gt; network interface for routing packets related to the default bridge network.&lt;&#x2F;p&gt;
&lt;p&gt;Using &lt;code&gt;nsenter&lt;&#x2F;code&gt; we can find more details about the network namespace created for an alloc. Let’s find details about the &lt;code&gt;redis&lt;&#x2F;code&gt; alloc:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nsenter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;pgrep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-net&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; addr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;1:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lo:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;LOOPBACK,UP,LOWER_U&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mtu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 65536&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; qdisc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; noqueue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; UNKNOWN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; qlen&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    link&#x2F;loopback&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 00:00:00:00:00:00&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; brd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 00:00:00:00:00:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    inet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 127.0.0.1&#x2F;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; scope&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; lo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;       valid_lft&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; forever&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; preferred_lft&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; forever&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;2:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0@if113:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;BROADCAST,MULTICAST,UP,LOWER_U&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mtu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1500&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; qdisc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; noqueue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; UP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    link&#x2F;ether&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 76:47:6d:49:00:c0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; brd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ff:ff:ff:ff:ff:ff&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; link-netnsid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    inet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.5&#x2F;20&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; brd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.79.255&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; scope&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; global&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;       valid_lft&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; forever&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; preferred_lft&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; forever&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see that one end of the pair is &lt;code&gt;eth0&lt;&#x2F;code&gt; (container’s default gateway) which is connected to a network interface with an index &lt;code&gt;113&lt;&#x2F;code&gt;. For the tunnel to actually work, the veth pair should also exist on the host:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;113:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; veth3402deda@if2:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;BROADCAST,MULTICAST,UP,LOWER_U&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mtu&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1500&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; qdisc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; noqueue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; master&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; UP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    link&#x2F;ether&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 3a:85:1b:37:75:17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; brd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ff:ff:ff:ff:ff:ff&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; link-netnsid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    inet6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fe80::3885:1bff:fe37:7517&#x2F;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; scope&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; link&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;       valid_lft&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; forever&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; preferred_lft&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; forever&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, when we see &lt;code&gt;veth3402deda@if2&lt;&#x2F;code&gt; in the host’s network namespace (with the index &lt;code&gt;113&lt;&#x2F;code&gt;), and then we see &lt;code&gt;eth0@if113&lt;&#x2F;code&gt; inside the Redis container, we can infer that these two interfaces form a &lt;code&gt;veth&lt;&#x2F;code&gt; pair: &lt;code&gt;veth3402deda@if2&lt;&#x2F;code&gt; on the host side and &lt;code&gt;eth0&lt;&#x2F;code&gt; inside the container. This connection enables the container to communicate with the external network through the host’s network stack.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;capturing-packets&quot;&gt;Capturing packets&lt;a class=&quot;zola-anchor&quot; href=&quot;#capturing-packets&quot; aria-label=&quot;Anchor link for: capturing-packets&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We can capture TCP packets on the &lt;code&gt;veth&lt;&#x2F;code&gt; interface to see the routing work:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tcpdump&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; veth971858d5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcpdump:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; verbose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; suppressed,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; use&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; full&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; protocol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; decode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;listening&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; on&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; veth971858d5,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; link-type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; EN10MB&lt;&#x2F;span&gt;&lt;span&gt; (Ethernet&lt;&#x2F;span&gt;&lt;span&gt;), snapshot length 262144 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.801319&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1.35826&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.7000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [S&lt;&#x2F;span&gt;&lt;span&gt;], seq 1331933249, win 65495, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;mss 65495,sackOK,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;248300785&lt;&#x2F;span&gt;&lt;span&gt; ecr 0,nop,wscale 7&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.801549&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.6.7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.1.35826:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [S.&lt;&#x2F;span&gt;&lt;span&gt;], seq 107697826, ack 1331933250, win 65160, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;mss 1460,sackOK,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3965422857&lt;&#x2F;span&gt;&lt;span&gt; ecr 248300785,nop,wscale 7&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.801616&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1.35826&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.7000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 1, win 512, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;248300785&lt;&#x2F;span&gt;&lt;span&gt; ecr 3965422857&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.801737&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1.35826&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.7000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [P.&lt;&#x2F;span&gt;&lt;span&gt;], seq 1:79, ack 1, win 512, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;248300786&lt;&#x2F;span&gt;&lt;span&gt; ecr 3965422857&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 78&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.801751&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.6.7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.1.35826:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 79, win 509, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3965422858&lt;&#x2F;span&gt;&lt;span&gt; ecr 248300786&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.802022&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.6.7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.1.35826:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [P.&lt;&#x2F;span&gt;&lt;span&gt;], seq 1:4097, ack 79, win 509, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3965422858&lt;&#x2F;span&gt;&lt;span&gt; ecr 248300786&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 4096&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.802059&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1.35826&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.7000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 4097, win 491, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;248300786&lt;&#x2F;span&gt;&lt;span&gt; ecr 3965422858&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.802120&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.6.7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.1.35826:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [P.&lt;&#x2F;span&gt;&lt;span&gt;], seq 4097:5396, ack 79, win 509, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3965422858&lt;&#x2F;span&gt;&lt;span&gt; ecr 248300786&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 1299&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.802135&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1.35826&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.7000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 5396, win 502, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;248300786&lt;&#x2F;span&gt;&lt;span&gt; ecr 3965422858&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.803484&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1.35826&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.7000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [F.&lt;&#x2F;span&gt;&lt;span&gt;], seq 79, ack 5396, win 512, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;248300787&lt;&#x2F;span&gt;&lt;span&gt; ecr 3965422858&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.803567&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.6.7000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.1.35826:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [F.&lt;&#x2F;span&gt;&lt;span&gt;], seq 5396, ack 80, win 509, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3965422859&lt;&#x2F;span&gt;&lt;span&gt; ecr 248300787&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:51:27.803597&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.1.35826&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.7000:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 5397, win 512, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;248300787&lt;&#x2F;span&gt;&lt;span&gt; ecr 3965422859&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:53:08.523431&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.6.53042&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 95.216.165.210.27372:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 2169295212, win 501, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;735542538&lt;&#x2F;span&gt;&lt;span&gt; ecr 4133067854&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:53:08.523551&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 95.216.165.210.27372&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.53042:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 1, win 509, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4133379150&lt;&#x2F;span&gt;&lt;span&gt; ecr 735231242&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:53:08.523554&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 95.216.165.210.27372&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 172.26.64.6.53042:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 1, win 509, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4133379150&lt;&#x2F;span&gt;&lt;span&gt; ecr 735231242&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10:53:08.523562&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.26.64.6.53042&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 95.216.165.210.27372:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt; [.&lt;&#x2F;span&gt;&lt;span&gt;], ack 1, win 501, options &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;nop,nop,TS val &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;735542538&lt;&#x2F;span&gt;&lt;span&gt; ecr 4133379150&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, length 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To summarize the output, we can see that the log is showing a TCP connection between 172.26.64.1 (source) and 172.26.64.6 (destination), specifically on port 7000. &lt;code&gt;172.26.64.1&lt;&#x2F;code&gt; happens to be the gateway for &lt;code&gt;nomad&lt;&#x2F;code&gt; subnet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Hope this post clarified some networking internals and behind the scenes magic when using Nomad bridge networking. Refer to my other post - &lt;a href=&quot;&#x2F;posts&#x2F;nomad-networking-explained&#x2F;&quot;&gt;Nomad networking explained&lt;&#x2F;a&gt; for a practical breakdown of all the different ways to expose and connect applications in a Nomad cluster.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Analyzing credit card transactions with GPT and Python</title>
        <published>2023-04-30T07:08:02+00:00</published>
        <updated>2023-04-30T07:08:02+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/analyzing-credit-card-transactions/"/>
        <id>https://mrkaran.dev/posts/analyzing-credit-card-transactions/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/analyzing-credit-card-transactions/">&lt;p&gt;You know those budget freaks? People who log and categorise every Rupee they’ve spent over the month? The financially sane people? I am definitely not one and I suck at it.&lt;&#x2F;p&gt;
&lt;p&gt;I moved cities a couple of months back and had some big ticket spends off late, mostly financed by credit card. I wanted an easy way to list down where all I’ve spent most money and spot some recurring expenses so I can be better prepared for them from next month. I’ve found that broadly keeping an idea of things where you spend money works for me (v&#x2F;s the two extremes - completely blind or logging every small transactions). Of course I know people who make budgeting a habit but I only wish I was consistent enough to do that.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I downloaded the statement in CSV format from my bank.&lt;&#x2F;p&gt;
&lt;p&gt;Initially I thought I’d use some simple Excel to make sense of this but I realised how bad my Excel skills really are. I got an idea to dump the CSV file to ChatGPT (yay privacy) and ask questions. It kinda sucked at it and gave wrong answers for a lot of questions and also started to hallucinate data which wasn’t even present in the CSV.&lt;&#x2F;p&gt;
&lt;p&gt;The next most obvious step would be to write a simple script and parse it. I wanted to experiment if ChatGPT could do this entire exercise of writing the script and the relevant code for the analysis I wanted to perform.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the initial prompt I gave:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;I am pasting a CSV file which also includes the first row as header. Write Python code to parse this:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;,,Transaction Date,Details,,,Amount (INR),,,Reference Number,,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;,,27&#x2F;04&#x2F;2023,&amp;quot;Blinkit, BANGALORE, IN&amp;quot;,,,290.00 Dr.,,,7477468633,,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... other data ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It returned the following code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; pandas&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; pd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; io&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; StringIO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;csv_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,,Transaction Date,Details,,,Amount (INR),,,Reference Number,,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,,27&#x2F;04&#x2F;2023,&amp;quot;Blinkit, BANGALORE, IN&amp;quot;,,,290.00 Dr.,,,747746xxxx,,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;# ... (the rest of your CSV data)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,,03&#x2F;04&#x2F;2023,&amp;quot;DIGITAL LOUNGE, GURGAON, IN&amp;quot;,,,799.00 Dr.,,,738201xxx,,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Read the CSV data into a pandas DataFrame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; StringIO&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;csv_data&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; pd&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read_csv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; header&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Clean up the DataFrame (remove unnecessary columns)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;dropna&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;axis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; how&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;all&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Rename columns&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;columns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Transaction Date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Reference Number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking at this, I was a bit impressed as it figured the CSV contains some useless empty columns and it removed (without me giving any information about it).&lt;&#x2F;p&gt;
&lt;p&gt;I also asked it to modify the code to read the file locally from disk and it swapped &lt;code&gt;StringIO&lt;&#x2F;code&gt; with the path to CSV file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Provide the file path to your local CSV file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;your_file.csv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Read the CSV data into a pandas DataFrame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; pd&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read_csv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; header&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;analyzing-credit-card-transactions-1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Next, I prompted to do some analysis on it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Write some more code to do the analysis to answer these questions:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- How many total debit and credit entries&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- What is the total amount of debits and total amount of credits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Which vendor have I spent the most?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- How much have I spent on `SWIGGY` ?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It returned some one-liners to answer each question:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Filter debit and credit entries&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;debit_entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;credit_entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Count the total number of debit and credit entries&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;total_debit_entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;debit_entries&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;total_credit_entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;credit_entries&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Calculate the total amount of debits and credits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;total_debit_amount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; debit_entries&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;total_credit_amount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; credit_entries&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Find the vendor with the most spending&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;most_spent_vendor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; debit_entries&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;groupby&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;idxmin&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Calculate the total amount spent on SWIGGY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;swiggy_spending&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; debit_entries&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;debit_entries&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;str&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;contains&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;SWIGGY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Calculate the total amount spent on AMAZON RECHARGES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;amazon_recharges_spending&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; debit_entries&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;debit_entries&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;str&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;contains&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;AMAZON RECHARGES&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Print the results&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Total debit entries: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;total_debit_entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Total credit entries: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;total_credit_entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Total debit amount: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;total_debit_amount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Total credit amount: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;total_credit_amount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Vendor with the most spending: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;most_spent_vendor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Total amount spent on SWIGGY: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;swiggy_spending&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At this point, I know that this will fail because we’ve not cleaned up the data. The column &lt;code&gt;Amount (INR)&lt;&#x2F;code&gt; needs cleaning up. I prompted ChatGPT to write a function to clean this column:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;The amount column as `21,620.54 Dr.` to represent that Rs 21,620.54 is debited. And `73,500.00 Cr.` to represent that Rs 73,500.00 is credited. Can you write a function to apply this transformation on the `Amount (INR)` column?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It responded with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Clean up the data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; clean_amount&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Cr.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Cr.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;value&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    elif&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Dr.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Dr.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; float&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;value&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;clean_amount&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Now proceed with the analysis code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! After transforming the amounts, I ran the analysis code:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;analyzing-credit-card-transactions-2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The next prompt I gave was to analyse the spending in various categories.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;In the above CSV file can you guess the categories of each merchant based on the `Details`? And write the code for grouping the spends on various categories. If you&amp;#39;re unable to figure out the category for the transaction, you can use a &amp;quot;Misc&amp;quot; column to bucket them.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It actually did an okayish job at this and ignored a lot of vendors which I think it could have guessed easily:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; categorize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;details&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lower&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;swiggy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Food Delivery&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    elif&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;amazon recharges&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Recharge&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    elif&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;uber&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ola&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Cab&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    elif&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;zomato&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Food Delivery&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    elif&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;netflix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;prime video&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; details&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Streaming&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Misc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Create a new column called &amp;quot;Category&amp;quot; by applying the categorize function to the &amp;quot;Details&amp;quot; column&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Category&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Details&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;categorize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Group the transactions by category and calculate the total amount spent in each category&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;grouped&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;groupby&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Category&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;grouped&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I decided to give some manual inputs to it to refine the function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;I can help you with categorising it further.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;`Blink` -  Grocery&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;`Indigo` - Travel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;`PEGS` - Alcohol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;`Nike` - Shopping&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Also note that the cateorgy name matching should be case-insensitive.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And it modified the Python snippet to add these rules.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;analyzing-credit-card-transactions-3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Mixed reactions looking at this. Happy that I could practically get exactly the result I had in mind in just 10 minutes without writing any code. Sad because damn I need to limit those empty calories from next month (famous last words).&lt;&#x2F;p&gt;
&lt;p&gt;Next, I wanted to see if my spends on weekends are higher or not. (I don’t expect them to be, but you never know).&lt;&#x2F;p&gt;
&lt;p&gt;Prompt:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Can you also write the code to figure how much spends I&amp;#39;ve done grouped by the day of week?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Response:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Convert the &amp;#39;Transaction Date&amp;#39; column to a datetime format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Transaction Date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; pd&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;to_datetime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Transaction Date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Create a new column called &amp;quot;Day of Week&amp;quot; containing the day of the week for each transaction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Day of Week&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Transaction Date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;dt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;day_name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Group the transactions by the &amp;quot;Day of Week&amp;quot; and calculate the total amount spent on each day of the week&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;grouped_by_day&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;df&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;groupby&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Day of Week&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Amount (INR)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;abs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Sort the grouped data by the total amount spent in descending order&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sorted_grouped_by_day&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; grouped_by_day&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sort_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;ascending&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;sorted_grouped_by_day&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;analyzing-credit-card-transactions-4.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;It was a fun 10-15 min exercise to figure out my spending habits based on the last month’s statement. I intend to do this for the next couple of months and then it would make sense to write more queries which would show trend-lines of spends in various categories over time.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly, I just loved how ChatGPT made this task so seemingly simple. It’s not that I can’t myself write the code for these kind of simple analysis. It’s the sheer power at your hand to go from ideation phase to answer within seconds. And I think that’s why I love it so much. I didn’t have to go through Pandas docs (because I don’t use that in my day job so it’s quite normal to not know various syntax&#x2F;functions that I could use) and I’d grok through different StackOverflow questions to achieve what I wanted to. And maybe imagining all this resistance on a Sunday morning would have meant that I never got to write the script in the first place.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The curious case of missing and duplicate logs</title>
        <published>2023-02-16T08:27:13+00:00</published>
        <updated>2023-02-16T08:27:13+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/missing-duplicate-logs/"/>
        <id>https://mrkaran.dev/posts/missing-duplicate-logs/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/missing-duplicate-logs/">&lt;p&gt;At work, we use a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;&quot;&gt;Vector&lt;&#x2F;a&gt; pipeline for processing and shipping logs to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;&quot;&gt;Clickhouse&lt;&#x2F;a&gt;. We also self-host our SMTP servers and recently started using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haraka&#x2F;Haraka&quot;&gt;Haraka SMTP&lt;&#x2F;a&gt;. While Haraka is excellent in raw performance and throughput, it needed an external logging plugin for audit and compliance purposes. I wrote &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;haraka-plugin-outbound-logger&quot;&gt;haraka-plugin-outbound-logger&lt;&#x2F;a&gt; to log basic metadata like timestamps&#x2F;subject&#x2F;SMTP response in a JSON file.&lt;&#x2F;p&gt;
&lt;p&gt;The plan was to dump these logs into a file and use Vector’s file source for reading them and doing the further transformation. However, things went differently than I had planned. There were mainly two issues propped up due to bad Vector configuration.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;missing-logs&quot;&gt;Missing logs&lt;a class=&quot;zola-anchor&quot; href=&quot;#missing-logs&quot; aria-label=&quot;Anchor link for: missing-logs&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The vector configuration to read the file looked like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;outbound_logger&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;include&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;var&#x2F;log&#x2F;haraka&#x2F;outbound&#x2F;*.log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;read_from&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;beginning&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Remove the files after 24 hours. Vector must have permission to delete these files.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;remove_after_secs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 86400&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fingerprint&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strategy&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;device_and_inode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Vector has a handy configuration of &lt;em&gt;automagically&lt;&#x2F;em&gt; deleting the file if the file hasn’t received any new write in the configured time interval. So &lt;code&gt;remove_after_secs=86400&lt;&#x2F;code&gt; specifies if the file hasn’t had any new writes since 24h, it can delete it. It made sense to configure because our workload was a shorter process. It was a batch job done once every N days.&lt;&#x2F;p&gt;
&lt;p&gt;When the file didn’t receive any new writes after 24h, &lt;code&gt;vector&lt;&#x2F;code&gt; deleted the file as expected. However, the plugin continued logging into the &lt;em&gt;same&lt;&#x2F;em&gt; file handler, even for newer batch jobs. As a result, the file didn’t receive any new logs and was empty.&lt;&#x2F;p&gt;
&lt;p&gt;I created a minimal POC to reproduce this seemingly strange issue:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;var&lt;&#x2F;span&gt;&lt;span&gt; pino&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pino&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Initialise pino js logger and inject in the plugin context.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;var&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;outbound_logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    level&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;debug&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; uses the ISO time format.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    timestamp&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; pino&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stdTimeFunctions&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;isoTime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    formatters&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;        level&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;label&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; level&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; label&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pilog&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; pino&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;opts&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; pino&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;destination&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;__dirname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;app.log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pilog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;this is a first message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;setTimeout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; pilog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;this message should get logged&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10000&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pilog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;this message will be recorded as well&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This snippet logs to &lt;code&gt;app.log&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;info&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2023-02-16T06:45:04.031Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;pid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;206573&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pop-os&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;outbound_logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;this is a first message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;info&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2023-02-16T06:45:04.031Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;pid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;206573&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pop-os&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;outbound_logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;this message will be recorded as well&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;During the 10s time interval, I deleted the file from the disk &lt;code&gt;rm app.log&lt;&#x2F;code&gt; to mimic the behaviour of &lt;code&gt;remove_after_secs&lt;&#x2F;code&gt;. I expected the file to get re-created and &lt;code&gt;this message should get logged&lt;&#x2F;code&gt; logged by the above script.&lt;&#x2F;p&gt;
&lt;p&gt;However, that &lt;strong&gt;didn’t&lt;&#x2F;strong&gt; happen. The script didn’t complain about a missing file, either. I was perplexed and did some google-fu and found the following via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;19304284&#x2F;709452&quot;&gt;Stackoverflow&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The writes actually do not fail.When you delete a file that is open in another program you are deleting a named link to that file’s inode. The program that has it open still points to that inode. It will happily keep writing to it, actually writing to disk. Only now you don’t have a way to look it at, because you deleted the named reference to it. (If there were other references, e.g. hard links, you would still be able to!).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is exactly what was happening in production. When &lt;code&gt;vector&lt;&#x2F;code&gt; deleted the file (as configured via &lt;code&gt;remove_after_secs&lt;&#x2F;code&gt; ), the plugin didn’t know about it and kept writing to the same inode. This was a major TIL moment for me.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Fix&lt;&#x2F;strong&gt;: The fix was simple enough; I removed &lt;code&gt;remove_after_secs&lt;&#x2F;code&gt; from Vector’s config. To address the problem of the file not growing unbounded forever, I created a &lt;code&gt;logrotate&lt;&#x2F;code&gt; config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;opt&#x2F;app&#x2F;logs&#x2F;app.log {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    daily&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rotate 15&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dateext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dateformat -%Y-%m-%d.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    delaycompress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    compress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    notifempty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    missingok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    copytruncate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;copytruncate&lt;&#x2F;code&gt; is useful in this context. It copies the existing file to a new one, which now becomes a stale one. The current (active) file will be truncated to zero bytes. E.g., if &lt;code&gt;app.log&lt;&#x2F;code&gt; it is rotated, logrotate will copy the file to a new file &lt;code&gt;app-2023-02-05.log&lt;&#x2F;code&gt; and then truncate the existing one to zero bytes.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;delaycompress&lt;&#x2F;code&gt; will not compress the logs until the next rotation happens. This is useful if &lt;code&gt;vector&lt;&#x2F;code&gt; hasn’t finished processing the log and can continue to do that.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;duplicate-logs&quot;&gt;Duplicate Logs&lt;a class=&quot;zola-anchor&quot; href=&quot;#duplicate-logs&quot; aria-label=&quot;Anchor link for: duplicate-logs&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now after fixing the case of missing logs, I found myself in the opposite problem - now the logs were &lt;em&gt;duplicated&lt;&#x2F;em&gt; on Clickhouse.&lt;&#x2F;p&gt;
&lt;p&gt;My mental state at that moment couldn’t be more accurately described than this meme:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;missing-duplicate-logs-this-is-fine.jpeg&quot; alt=&quot;img&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To add more context, before developing my plugin for logging email delivery in Haraka, we used another plugin (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;acharkizakaria&#x2F;haraka-plugin-accounting-files&quot;&gt;acharkizakaria&#x2F;haraka-plugin-accounting-files&lt;&#x2F;a&gt;) to get these logs. This plugin records the metadata to CSV files. Still, there were some issues in properly escaping the subject lines (if the subject had a comma, that was incorrectly parsed); hence, the log file had inconsistent output. To address these issues, I found writing another plugin from scratch that outputs to a fixed JSON schema is better.&lt;&#x2F;p&gt;
&lt;p&gt;As seen above, &lt;code&gt;vector&lt;&#x2F;code&gt;’s file source was configured like the following for reading CSV files. The only change here is that &lt;code&gt;remove_after_secs&lt;&#x2F;code&gt; is gone after fixing issue #1.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;outbound_logger&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;include&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;var&#x2F;log&#x2F;haraka&#x2F;outbound&#x2F;*.log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;read_from&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;beginning&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fingerprint&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;strategy&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;device_and_inode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Vector “&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;configuration&#x2F;sources&#x2F;file&#x2F;#fingerprint&quot;&gt;fingerprints&lt;&#x2F;a&gt;” the file source, as it keeps the checkpoint of how many bytes it has read for each file in its own “disk buffer”. This buffer is helpful if Vector crashes so it can restart reading the file from where it last stopped.&lt;&#x2F;p&gt;
&lt;p&gt;There are two strategies for fingerprinting that vector uses:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;checksum&lt;&#x2F;code&gt; strategy uses CRC check on the first N lines of the file.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;device_and_inode strategy&lt;&#x2F;code&gt; uses the disk’s actual inode location to identify the file uniquely.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As I was using a different plugin which logged to a CSV file, the checksum strategy did not work in my context. Since vector fingerprints, the first few bytes (usually just enough for a header of a CSV), all the CSV files in that disk would have the same title, and Vector would not read all of them. To work around this, I changed the &lt;code&gt;fingerprint.starategy = &quot;device_and_inode&quot;&lt;&#x2F;code&gt; so Vector uniquely identifies all CSV files by their inode path. (In hindsight, I should have just used &lt;code&gt;checksum&lt;&#x2F;code&gt; with a higher value of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;configuration&#x2F;sources&#x2F;file&#x2F;#fingerprint.lines&quot;&gt;fingerprint.lines&lt;&#x2F;a&gt; value.)&lt;&#x2F;p&gt;
&lt;p&gt;The mistake this time was when I switched to a JSON log file, I continued with the &lt;code&gt;device_and_inode&lt;&#x2F;code&gt; strategy. This isn’t a problem if there is no log rotation setup. Since I did configure &lt;code&gt;logrotate&lt;&#x2F;code&gt; to fix issue #1, as you would have guessed, &lt;code&gt;copytruncate&lt;&#x2F;code&gt; created another log file, and because I was using &lt;code&gt;device_and_inode&lt;&#x2F;code&gt; strategy, vector thought this was a “new” file to be watched and processed. So now I had duplicate entries from this new file, which is technically just an older log-rotated file.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;outbound_logger&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;fingerprint&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lines&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 14&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;strategy&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ignored_header_bytes&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2048&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I switched back to the default &lt;code&gt;checksum&lt;&#x2F;code&gt; strategy and adjusted the thresholds for lines&#x2F;header bytes to account for JSON logs. The same is also &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;configuration&#x2F;sources&#x2F;file&#x2F;#file-rotation&quot;&gt;documented&lt;&#x2F;a&gt; very clearly in Vector and it was my RTFM moment.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This strategy avoids the common pitfalls associated with using device and inode names since inode names can be reused across files. This enables Vector to properly tail files across various rotation strategies.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Phew! I am glad after these fixes; &lt;code&gt;vector&lt;&#x2F;code&gt; is durably and reliably processing all the logs and &lt;code&gt;logrotate&lt;&#x2F;code&gt; is happily working in conjunction as well. I hope documenting my learnings about these production issues would help someone with the same problems.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Structured logging in Go with slog</title>
        <published>2023-02-15T07:29:53+00:00</published>
        <updated>2023-02-15T07:29:53+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/structured-logging-in-go-with-slog/"/>
        <id>https://mrkaran.dev/posts/structured-logging-in-go-with-slog/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/structured-logging-in-go-with-slog/">&lt;p&gt;A few months ago, a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;issues&#x2F;56345&quot;&gt;proposal&lt;&#x2F;a&gt; for adding a structured logging library in Go was introduced by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jba&quot;&gt;Jonathan Amsterdam&lt;&#x2F;a&gt;. At present, Go has a minimal and bare-bones log package which works all right for basic use cases. However, the current library has a few shortcomings that this proposal aims to solve:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Emitting logs with different severity&#x2F;levels&lt;&#x2F;li&gt;
&lt;li&gt;Structured output: Makes parsing of logs harder&lt;&#x2F;li&gt;
&lt;li&gt;Logging a set of common fields&#x2F;attributes&lt;&#x2F;li&gt;
&lt;li&gt;Difficult to have a log object inside libraries as each service could have its log implementation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As a result, many code bases have their wrappers around the log package. Additionally, there are plenty of 3rd party libraries to choose from - including &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zerodha&#x2F;logf&quot;&gt;logf&lt;&#x2F;a&gt; (which my work colleagues and I built at Zerodha).&lt;&#x2F;p&gt;
&lt;p&gt;This article is about how to get started with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkg.go.dev&#x2F;golang.org&#x2F;x&#x2F;exp&#x2F;slog&quot;&gt;slog&lt;&#x2F;a&gt; for logging in Go applications.&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;admonition note&quot;&gt;
    &lt;strong class=&quot;admonition-header&quot;&gt;NOTE&lt;&#x2F;strong&gt;
    &lt;p&gt;&lt;p&gt;Since slog is currently in the proposal state and hasn’t yet merged in the official library, the API could change in future.&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;architecture-of-slog&quot;&gt;Architecture of slog&lt;a class=&quot;zola-anchor&quot; href=&quot;#architecture-of-slog&quot; aria-label=&quot;Anchor link for: architecture-of-slog&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;At a higher level, slog contains three main entities:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Logger&lt;&#x2F;strong&gt;: The user-facing API for interacting with slog. All the public methods are defined on the Logger object.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Record&lt;&#x2F;strong&gt;: Contains information about the log event itself. A standard record will have timestamp, level and message fields as default. Additional attributes and metadata like caller info can be added to the Record.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Handlers&lt;&#x2F;strong&gt;: A handler is an &lt;em&gt;interface&lt;&#x2F;em&gt; implementation. The Logger object passes the Record to a handler, and the handler can choose whatever it wants to do with the Record. This is a common approach in Go libraries, where a “provider” can be abstracted in handling that task. Currently, slog ships with two handlers: JSON and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;brandur.org&#x2F;logfmt&quot;&gt;logfmt&lt;&#x2F;a&gt;. Some projects have also created handlers for zap&#x2F;logrus (popular 3rd party libraries).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;initialization&quot;&gt;Initialization&lt;a class=&quot;zola-anchor&quot; href=&quot;#initialization&quot; aria-label=&quot;Anchor link for: initialization&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This snippet initializes a Text Handler, which produces &lt;code&gt;logfmt&lt;&#x2F;code&gt; format messages on &lt;code&gt;os.Stdout&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;package&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;os&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;golang.org&#x2F;x&#x2F;exp&#x2F;slog&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;New&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewTextHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Stdout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	fakeErr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ErrNotExist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;something went wrong&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fakeErr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;tmp&#x2F;abc.txt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Log output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;F&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;something went wrong&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;file does not exist&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;customizing&quot;&gt;Customizing&lt;a class=&quot;zola-anchor&quot; href=&quot;#customizing&quot; aria-label=&quot;Anchor link for: customizing&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You’ll notice that the caller information isn’t exposed by default. The reason could be that finding the stack trace of the calling line is a bit expensive operation. However, for libraries&#x2F;apps which need it can do that by customizing the handler:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	handler&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;HandlerOptions&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;AddSource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;New&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;handler&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewTextHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Stdout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Log Output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;F&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span&gt; source&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;attributes&quot;&gt;Attributes&lt;a class=&quot;zola-anchor&quot; href=&quot;#attributes&quot; aria-label=&quot;Anchor link for: attributes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes, it’s helpful to append specific metadata to each log line which will help in aggregating&#x2F;filtering with a central log-collecting agent. E.g., you can export a component key for each sub-service of your primary application.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;New&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewTextHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Stdout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;With&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;demo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Log Output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;F&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;nested-keys&quot;&gt;Nested Keys&lt;a class=&quot;zola-anchor&quot; href=&quot;#nested-keys&quot; aria-label=&quot;Anchor link for: nested-keys&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;So far, we’ve seen flat keys in the log message. It may be helpful to group together specific keys together and form a nested object. In JSON, that would mean a top-level object with different fields inside. However, in &lt;code&gt;logfmt&lt;&#x2F;code&gt;, it would-be &lt;code&gt;parent.child&lt;&#x2F;code&gt; format.To use nested keys, &lt;code&gt;slog.Group&lt;&#x2F;code&gt; can be used. This example uses &lt;code&gt;http&lt;&#x2F;code&gt; as the top-level key, and all its associated fields will be nested inside.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;http&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;method&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;GET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 250&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;method&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;GET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;api&#x2F;health&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;F&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; http.method&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http.status=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;200&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http.duration=250ns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http.method=GET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http.path=&#x2F;api&#x2F;health&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;configurable-handlers&quot;&gt;Configurable Handlers&lt;a class=&quot;zola-anchor&quot; href=&quot;#configurable-handlers&quot; aria-label=&quot;Anchor link for: configurable-handlers&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;JSON logs are daunting and tedious to read when locally developing applications. However, it’s a great fit for machine parsing of the logs. &lt;code&gt;logfmt&lt;&#x2F;code&gt; hits the sweet spot for being machine parseable and human-readable.However, thanks to the powerful “interface” implementation approach, it’s easy to switch to any handler via user-configurable methods (like config files&#x2F;env variables):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;package&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;os&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;golang.org&#x2F;x&#x2F;exp&#x2F;slog&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		env&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;APP_ENV&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		handler&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Handler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	switch&lt;&#x2F;span&gt;&lt;span&gt; env&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;production&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		handler&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewJSONHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Stdout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	default&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		handler&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewTextHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Stdout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; slog&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;New&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;handler&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	log&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main.go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;F&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; APP_ENV=production&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; main.go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;2023-02-15T12:39:53.523477544+05:30&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;INFO&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;slog&lt;&#x2F;code&gt; is an excellent proposal, and it’s high time Go gets its official structured logging library. The API is designed to be easy to use, and a clear path is given for users wanting high-performance&#x2F;zero-allocs by creating their handlers and making these performance improvements.&lt;&#x2F;p&gt;
&lt;p&gt;Fin&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Building a CoreDNS plugin</title>
        <published>2023-01-05T00:00:00+05:30</published>
        <updated>2023-01-05T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/coredns-nomad/"/>
        <id>https://mrkaran.dev/posts/coredns-nomad/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/coredns-nomad/">&lt;p&gt;CoreDNS is an extensible DNS server (which is actually a fork of Caddy v1) that can be used to serve DNS records for a domain. It is written in Go and is very easy to extend. It has a plugin system that allows you to write your own plugins to extend its functionality. In this post, I will be writing a plugin for CoreDNS that will allow it to serve DNS records for Nomad services.&lt;&#x2F;p&gt;
&lt;p&gt;I recently came across a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;12588#issuecomment-1368679059&quot;&gt;niche use case&lt;&#x2F;a&gt; which required me to use a resolver address for querying Nomad services. Currently Nomad native service discovery is only possible via &lt;code&gt;consul-template&lt;&#x2F;code&gt; (which renders static block of address&#x2F;port of services) and HTTP API. I felt adding a DNS interface would be a nice add-on.&lt;&#x2F;p&gt;
&lt;p&gt;Rather than writing and implementing all the boring crux of a DNS server, it’s better to extend on an existing server. CoreDNS fits in well here, it’s also used by K8s for service discovery. CoreDNS has an extensible plugin system which allows you to chain multiple different plugins for handling a request. Stuff like logs&#x2F;metrics&#x2F;caching comes for free with CoreDNS in form of a plugin.&lt;&#x2F;p&gt;
&lt;p&gt;CoreDNS docs have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coredns&#x2F;coredns&#x2F;blob&#x2F;master&#x2F;plugin.md#writing-plugins&quot;&gt;handy guide&lt;&#x2F;a&gt; on how to write a plugin from scratch, so I won’t cover that again here. These are just my short notes on how I locally developed the plugin, tested and some problems I encountered during the process.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;developing-the-plugin&quot;&gt;Developing the plugin&lt;a class=&quot;zola-anchor&quot; href=&quot;#developing-the-plugin&quot; aria-label=&quot;Anchor link for: developing-the-plugin&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Firstly, you need to clone CoreDNS repo. Then, using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coredns&#x2F;example&quot;&gt;example&lt;&#x2F;a&gt; plugin provided, you can create a new repository for your own plugin.&lt;&#x2F;p&gt;
&lt;p&gt;To make CoreDNS aware about this plugin, you need to add it to the &lt;code&gt;plugin.cfg&lt;&#x2F;code&gt; file. This file is used by the build script to generate the plugin list. The order of plugins matter here as they define how the request is handled. For example, if you want to log all the requests, you need to add the &lt;code&gt;log&lt;&#x2F;code&gt; plugin before your plugin.&lt;&#x2F;p&gt;
&lt;p&gt;To add an external plugin this is the format used:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nomad:github.com&#x2F;mr-karan&#x2F;coredns-nomad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, since we are developing the plugin locally, we need to add a &lt;code&gt;replace&lt;&#x2F;code&gt; directive in &lt;code&gt;go.mod&lt;&#x2F;code&gt; file to point to the local plugin directory.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;replace&lt;&#x2F;span&gt;&lt;span&gt; github&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;mr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;karan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; .&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;nomad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, you can run &lt;code&gt;make&lt;&#x2F;code&gt; in &lt;code&gt;coredns&lt;&#x2F;code&gt; repository. It’ll build the binary and place it in &lt;code&gt;coredns&lt;&#x2F;code&gt; directory. You can run this binary to test your plugin. To check if the plugin indeed exists in the binary, you can use the following command&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;.&#x2F;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;plugins&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nomad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;handling-requests&quot;&gt;Handling requests&lt;a class=&quot;zola-anchor&quot; href=&quot;#handling-requests&quot; aria-label=&quot;Anchor link for: handling-requests&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;ServeDNS&lt;&#x2F;code&gt; function is used to handle the DNS request by the plugin. It takes a &lt;code&gt;context.Context&lt;&#x2F;code&gt; and a &lt;code&gt;dns.ResponseWriter&lt;&#x2F;code&gt; as arguments. The &lt;code&gt;dns.ResponseWriter&lt;&#x2F;code&gt; is used to write the response back to the client. The &lt;code&gt;ServeDNS&lt;&#x2F;code&gt; function returns an &lt;code&gt;int&lt;&#x2F;code&gt; which is the status code of the response. The status code is used by the next plugin in the chain to determine if it should handle the request or not.&lt;&#x2F;p&gt;
&lt;p&gt;Since the &lt;code&gt;nomad&lt;&#x2F;code&gt; plugin expects a query in format of &lt;code&gt;service.namespace.nomad&lt;&#x2F;code&gt;, it validates the query and extracts the service name and namespace from it. If the query is invalid, it returns &lt;code&gt;dns.RcodeServerFailure&lt;&#x2F;code&gt; status code. If the query is valid, it queries the Nomad API for the service and returns the response.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;n &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Nomad&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; ServeDNS&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; dns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ResponseWriter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Msg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; request&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;W&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; w&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; Req&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	qname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	qtype&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;QType&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Split the query name with a `.` as the delimiter and extract namespace and service name.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; If the query is not for a Nomad service, return.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	qnameSplit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; dns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;SplitDomainName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;qname&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;qnameSplit&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; qnameSplit&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span&gt; plugin&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NextOrFailure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Next&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; ctx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; w&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	namespace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; qnameSplit&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	serviceName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; qnameSplit&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The plugin handles A,AAAA and SRV record requests currently. Since A&#x2F;AAAA records can only contain an IP address, SRV records can be used to advertise the port number.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Check the query type to format the appriopriate response.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		switch&lt;&#x2F;span&gt;&lt;span&gt; qtype&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span&gt; dns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;TypeA&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			m&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Answer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;m&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Answer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				Hdr&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; header&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				A&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;   addr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span&gt; dns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;TypeAAAA&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			m&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Answer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;m&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Answer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;AAAA&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				Hdr&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;  header&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				AAAA&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; addr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;caching&quot;&gt;Caching&lt;a class=&quot;zola-anchor&quot; href=&quot;#caching&quot; aria-label=&quot;Anchor link for: caching&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;While some coredns plugins have an in-built support for caching the records to avoid a lookup to Nomad server everytime (which can get expensive), I decided to skip the caching implementation. This is because &lt;code&gt;coredns&lt;&#x2F;code&gt; itself has a &lt;code&gt;cache&lt;&#x2F;code&gt; plugins which supports a lot of various options for controlling the cache. In my testing, just using this &lt;code&gt;cache&lt;&#x2F;code&gt; plugin was sufficient to avoid Nomad lookups each time a query came in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing-the-plugin&quot;&gt;Testing the plugin&lt;a class=&quot;zola-anchor&quot; href=&quot;#testing-the-plugin&quot; aria-label=&quot;Anchor link for: testing-the-plugin&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I created a fake HTTP test server and added the URI paths which the Nomad Go client uses to query the Nomad API. This way I could test the plugin without having to run a Nomad cluster locally.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Setup a fake Nomad server.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	nomadServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; httptest&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewServer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;http&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;HandlerFunc&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; http&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ResponseWriter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		switch&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;URL&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Path&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		default&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			t&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Errorf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Not implemented: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;URL&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;v1&#x2F;service&#x2F;example&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			w&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[{&amp;quot;Address&amp;quot;:&amp;quot;1.2.3.4&amp;quot;,&amp;quot;Namespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;Port&amp;quot;:23202,&amp;quot;ServiceName&amp;quot;:&amp;quot;example&amp;quot;}]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;v1&#x2F;service&#x2F;fakeipv6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			w&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[{&amp;quot;Address&amp;quot;:&amp;quot;1:2:3::4&amp;quot;,&amp;quot;Namespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;Port&amp;quot;:8000,&amp;quot;ServiceName&amp;quot;:&amp;quot;fakeipv6&amp;quot;}]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;v1&#x2F;service&#x2F;multi&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			w&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[{&amp;quot;Address&amp;quot;:&amp;quot;1.2.3.4&amp;quot;,&amp;quot;Namespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;Port&amp;quot;:25395,&amp;quot;ServiceName&amp;quot;:&amp;quot;multi&amp;quot;},{&amp;quot;Address&amp;quot;:&amp;quot;1.2.3.5&amp;quot;,&amp;quot;Namespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;Port&amp;quot;:20888,&amp;quot;ServiceName&amp;quot;:&amp;quot;multi&amp;quot;},{&amp;quot;Address&amp;quot;:&amp;quot;1.2.3.6&amp;quot;,&amp;quot;Namespace&amp;quot;:&amp;quot;default&amp;quot;,&amp;quot;Port&amp;quot;:26292,&amp;quot;ServiceName&amp;quot;:&amp;quot;multi&amp;quot;}]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;v1&#x2F;service&#x2F;nonexistent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			w&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;usage-example&quot;&gt;Usage Example&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage-example&quot; aria-label=&quot;Anchor link for: usage-example&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here are some examples of how this plugin works. The Corefile I’ve used is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nomad:1053 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    errors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    debug&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    health&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    nomad {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		address http:&#x2F;&#x2F;127.0.0.1:4646&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ttl 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    prometheus :9153&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cache 30&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On running &lt;code&gt;coredns&lt;&#x2F;code&gt;, it connects to a local Nomad agent which is running at &lt;code&gt;http:&#x2F;&#x2F;127.0.0.1:4646&lt;&#x2F;code&gt;. I’m running a &lt;code&gt;redis&lt;&#x2F;code&gt; job in Nomad, so I can query the service using the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; info&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;namespace=default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis&lt;&#x2F;span&gt;&lt;span&gt;                 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;              Tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Node&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Alloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   192.168.29.76:25395&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span&gt;]    9e02c85b  95170495&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   192.168.29.76:20888&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span&gt;]    9e02c85b  a1cf923c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   192.168.29.76:26292&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span&gt;]    9e02c85b  a9d1181a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, the same query can also be handled using the DNS server running by &lt;code&gt;coredns&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;doggo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.default.nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; @tcp:&#x2F;&#x2F;127.0.0.1:1053&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                	TYPE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	CLASS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	TTL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	ADDRESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      	NAMESERVER&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   	10s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	192.168.29.76&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	127.0.0.1:1053&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   	10s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	192.168.29.76&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	127.0.0.1:1053&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   	10s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	192.168.29.76&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	127.0.0.1:1053&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Quering an SRV record is also possible:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +noall&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +answer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +additional&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.default.nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; @127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1053&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; SRV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	SRV&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 25395&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.default.nomad.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	SRV&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 20888&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.default.nomad.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	SRV&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 26292&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.default.nomad.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	192.168.29.76&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	192.168.29.76&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.default.nomad.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	192.168.29.76&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;code&quot;&gt;Code&lt;a class=&quot;zola-anchor&quot; href=&quot;#code&quot; aria-label=&quot;Anchor link for: code&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can checkout the source code &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;coredns-nomad&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Writing a disk-based key-value store in Golang</title>
        <published>2022-12-18T00:00:00+05:30</published>
        <updated>2022-12-18T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/barreldb/"/>
        <id>https://mrkaran.dev/posts/barreldb/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/barreldb/">&lt;p&gt;I’d been mulling around reading a computer science paper and implementing a project based on it. Distributed systems, Networking and Databases are some of the things that fascinate me a lot. However, I had been looking to implement a more approachable project to avoid getting inundated initially. And I happened to chance upon the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;riak.com&#x2F;assets&#x2F;bitcask-intro.pdf&quot;&gt;Bitcask paper&lt;&#x2F;a&gt; through Avinash’s project: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;avinassh&#x2F;py-caskdb&quot;&gt;CaskDB&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After giving a quick read of this reasonably short paper, I decided to write a Golang implementation of the same, as it looked like an exciting project. If you’re interested in checking out the complete project, checkout &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;barreldb&#x2F;&quot;&gt;BarrelDB&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Bitcask is a disk-based key-value storage engine designed for fast read and write operations. It is mainly in production use by Riak (which is a distributed database) as one of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.riak.com&#x2F;riak&#x2F;kv&#x2F;2.2.3&#x2F;setup&#x2F;planning&#x2F;backend&#x2F;bitcask&#x2F;index.html&quot;&gt;storage engines&lt;&#x2F;a&gt;. Bitcask under the hood has a straightforward yet clever design. It writes to the file in an append-only mode. This means that writes are performed only by appending to the end of the file, thus avoiding the need to perform any random disk I&#x2F;O seek.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s look at various components of Bitcask:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;format-of-the-record&quot;&gt;Format of the record&lt;a class=&quot;zola-anchor&quot; href=&quot;#format-of-the-record&quot; aria-label=&quot;Anchor link for: format-of-the-record&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;barreldb_record.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CRC: Stores the checksum of the value to ensure data consistency&lt;&#x2F;li&gt;
&lt;li&gt;Timestamp: Timestamp in UNIX format, stored as int32.&lt;&#x2F;li&gt;
&lt;li&gt;Expiry: If the record has an expiry defined, then the timestamp, in UNIX format, is stored as int32.&lt;&#x2F;li&gt;
&lt;li&gt;Key Size: Size of the key in bytes&lt;&#x2F;li&gt;
&lt;li&gt;Value Size: Size of the value in bytes&lt;&#x2F;li&gt;
&lt;li&gt;Key&lt;&#x2F;li&gt;
&lt;li&gt;Value&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This additional metadata stored alongside the key&#x2F;value is represented with a fixed-width header. Each field is represented as &lt;code&gt;int32&lt;&#x2F;code&gt;, so the total size of the header is 4*5 = 20 bytes. Here’s the code which encodes and decodes this record:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Record&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Header&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Header&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Value&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Header represents the fixed width fields present at the start of every record.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Header&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  uint32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; uint32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Expiry&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    uint32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    KeySize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   uint32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ValSize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   uint32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Encode takes a byte buffer, encodes the value of header and writes to the buffer.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;h &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Header&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; encode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Buffer&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; binary&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; binary&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;LittleEndian&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Decode takes a record object decodes the binary value the buffer.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;h &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Header&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; decode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;record&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; binary&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;NewReader&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;record&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; binary&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;LittleEndian&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The record is encoded in the binary format before storing it on the disk.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;datafile&quot;&gt;Datafile&lt;a class=&quot;zola-anchor&quot; href=&quot;#datafile&quot; aria-label=&quot;Anchor link for: datafile&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A “datafile” (term used for the DB file on disk) is an append-only record of all the write operations. An instance of Bitcask can have several datafiles. However, there’s only one “active” datafile. In BarrelDB, a goroutine runs in the background at regular intervals to check if the size of the active DB file has crossed the threshold and then rotates the active file. It appends this DB file to the list of “stale” data files. All the new writes only happen to the “active” data file, and the stale files are merged as a part of the “compaction” process (described later in the post).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;barreldb_data_dir.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here’s how a &lt;code&gt;datafile&lt;&#x2F;code&gt; is represented:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; DataFile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;RWMutex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    writer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;File&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reader&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;File&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    offset&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It contains different handlers for writing and reading the file. The reason we have 2 file handlers instead of re-using the same one is that the &lt;code&gt;writer&lt;&#x2F;code&gt; is only opened in an “append-only” mode. In addition, since the active file can be rotated, the writer can be set to &lt;code&gt;nil&lt;&#x2F;code&gt;, ensuring no new writes ever happen on that file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    writer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;OpenFile&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;O_APPEND&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;O_CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;O_WRONLY&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0644&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Errorf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;error opening file for writing db: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Create a reader for reading the db file.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reader&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Errorf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;error opening file for reading db: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;keydir&quot;&gt;KeyDir&lt;a class=&quot;zola-anchor&quot; href=&quot;#keydir&quot; aria-label=&quot;Anchor link for: keydir&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In addition to storing the file on disk, Bitcask also stores additional metadata, which defines how to retrieve the record. This hashtable is a map of keys with this metadata and is referred to as &lt;code&gt;KeyDir&lt;&#x2F;code&gt;. An important point to note here is that the &lt;code&gt;value&lt;&#x2F;code&gt; is &lt;em&gt;never&lt;&#x2F;em&gt; stored in this map. This makes it possible for Bitcask to handle datasets more significant than what the RAM can hold.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; KeyDir represents an in-memory hash for faster lookups of the key.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Once the key is found in the map, the additional metadata, like the offset record&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; and the file ID is used to extract the underlying record from the disk.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Advantage is that this approach only requires a single disk seek of the db file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; since the position offset (in bytes) is already stored.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; KeyDir&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Meta&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Meta represents some additional properties for the given key.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; The actual value of the key is not stored in the in-memory hashtable.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Meta&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    RecordSize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    RecordPos&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    FileID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, &lt;code&gt;RecordPos&lt;&#x2F;code&gt; tells the record’s position offset (in bytes) in the entire file. Since the position of the record is stored in memory along with the key, the retrieval of the key doesn’t require more than a &lt;em&gt;single&lt;&#x2F;em&gt; disk seek. Bitcask achieves really low latency even with many keys in the database. A file system read-ahead cache also helps boost the performance and comes for free - no need to design a separate caching mechanism.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;barreldb_key_lookup.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compaction&quot;&gt;Compaction&lt;a class=&quot;zola-anchor&quot; href=&quot;#compaction&quot; aria-label=&quot;Anchor link for: compaction&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As we looked at previously, a datafile is simply an append-only sequence of writes. Any modification of the key is merely a new record appended to the datafile. KeyDir overwrites the entry of the key with the new metadata, which contains the new location of the record. Thus all reads will automatically return the updated value.&lt;&#x2F;p&gt;
&lt;p&gt;Deletes are handled similarly by writing a “tombstone” record for the key. When the user requests the key after it’s been deleted, BarrelDB can check whether that value equals the tombstone value and return an appropriate error.&lt;&#x2F;p&gt;
&lt;p&gt;As you would have guessed, our database will grow unbounded if we don’t perform any garbage cleanup. The datafiles need to be pruned for deleting expired&#x2F;deleted records and merging all stale files in a single active file - to keep the number of opened files in check. All of these processes are together called “Compaction”.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s take a look at how each of these compaction routine works under the hood:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;merge&quot;&gt;Merge&lt;a class=&quot;zola-anchor&quot; href=&quot;#merge&quot; aria-label=&quot;Anchor link for: merge&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The merge process iterates over all the keys inside KeyDir and fetches their value. The value could come from a stale file as well. Once the new keys&#x2F;values are updated, it writes them to a new active file. All the old file handlers are closed, and the stale files are deleted from the disk. The KeyDir is updated similarly since the new records live in a different position&#x2F;file.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hints-file&quot;&gt;Hints File&lt;a class=&quot;zola-anchor&quot; href=&quot;#hints-file&quot; aria-label=&quot;Anchor link for: hints-file&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Bitcask paper describes a way of creating a “hints” file initially loaded in the database for faster startup time. This file is essential to bootstrap KeyDir after a cold startup. This avoids iterating over all data files and reading their values sequentially. In BarrelDB, &lt;code&gt;gob&lt;&#x2F;code&gt; encoding is used to dump the &lt;code&gt;KeyDir&lt;&#x2F;code&gt; map as a &lt;code&gt;gob&lt;&#x2F;code&gt; dump.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; generateHints encodes the contents of the in-memory hashtable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; as `gob` and writes the data to a hints file.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Barrel&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; generateHints&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; filepath&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;opts&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;dir&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; HINTS_FILE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keydir&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Encode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;During the startup, BarrelDB checks the presence of a &lt;code&gt;.hints&lt;&#x2F;code&gt; file, decodes this gob dump, and loads the data in &lt;code&gt;KeyDir&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;removing-expired-keys&quot;&gt;Removing expired keys&lt;a class=&quot;zola-anchor&quot; href=&quot;#removing-expired-keys&quot; aria-label=&quot;Anchor link for: removing-expired-keys&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A goroutine runs at a configurable interval to check if the value of the key has expired. If it has, it deletes the entry from KeyDir. During the following merge process, since this entry won’t be present in KeyDir, it’ll automatically be removed when the new datafile is created.&lt;&#x2F;p&gt;
&lt;p&gt;To check if the key has expired, a simple check, like comparing their timestamps in UNIX epoch format, is enough: &lt;code&gt;time.Now().Unix() &amp;gt; int64(r.Header.Expiry)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;redis-server&quot;&gt;Redis Server&lt;a class=&quot;zola-anchor&quot; href=&quot;#redis-server&quot; aria-label=&quot;Anchor link for: redis-server&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In addition to using BarrelDB as a Go library, I also implemented a redis-compatible server. I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tidwall&#x2F;redcon&quot;&gt;tidwall&#x2F;redcon&lt;&#x2F;a&gt; as an easy-to-use library to create a Redis-compatible server for Go applications. All I’d do was wrap BarrelDB API methods and define handlers for &lt;code&gt;SET&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;GET&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I was able to use &lt;code&gt;redis-cli&lt;&#x2F;code&gt; and connect to the BarrelDB server:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;127.0.0.1:6379&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; set&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hello&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; world&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;OK&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;127.0.0.1:6379&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;benchmarks&quot;&gt;Benchmarks&lt;a class=&quot;zola-anchor&quot; href=&quot;#benchmarks&quot; aria-label=&quot;Anchor link for: benchmarks&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can check the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;barreldb&#x2F;#benchmarks&quot;&gt;repo&lt;&#x2F;a&gt; for the actual benchmarks. However, I’d like to point out some inferences of the results from &lt;code&gt;redis-benchmark&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First, let’s send 100000 requests to the server using 50 parallel clients. This command creates a unique key for each &lt;code&gt;SET&lt;&#x2F;code&gt; operation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis-benchmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 50&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; set&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100000000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Summary:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  throughput&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; summary:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 145985.41&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; requests&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; per&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; second&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  latency&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; summary&lt;&#x2F;span&gt;&lt;span&gt; (msec&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;          avg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p50&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p95&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p99&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       max&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        0.179&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.016&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.183&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.207&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.399&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     1.727&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, 140k requests per second is not bad at all for a disk-based KV. But the exciting thing to note here is that the performance is predictable even if you increase the load by increasing clients:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis-benchmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; set&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100000000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Summary:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  throughput&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; summary:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 140845.08&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; requests&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; per&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; second&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  latency&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; summary&lt;&#x2F;span&gt;&lt;span&gt; (msec&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;          avg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p50&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p95&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p99&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       max&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        0.718&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.224&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.711&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.927&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     1.183&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     5.775&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we increase the number of requests (by 5x) as well, the throughput looks almost the same:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis-benchmark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; set&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 500000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 100000000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Summary:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  throughput&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; summary:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 138350.86&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; requests&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; per&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; second&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  latency&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; summary&lt;&#x2F;span&gt;&lt;span&gt; (msec&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;          avg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       min&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p50&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p95&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       p99&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       max&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        0.748&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.056&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.711&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0.879&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     1.135&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    63.135&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This magic is all because of the way Bitcask uses Log structured hash table (just append-only records for writing data). Even with a lot of records, all it has to do is to write to the end of the file, which avoids any expensive I&#x2F;O operations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Overall, I am happy with &lt;code&gt;BarrelDB&lt;&#x2F;code&gt; implementation as I covered everything described in the paper. This project had excellent learning outcomes for me. I spent a lot of time coming up with a design for structuring different components and their API methods and handling all the edge scenarios during the compaction process. Although, full credit to Bitcask as it kept its design so elegant and minimal yet achieved some significant numbers in the benchmarks. This is also a reminder that simple need not necessarily mean less powerful.&lt;&#x2F;p&gt;
&lt;p&gt;I look forward to implementing a distributed KV store by adding support for multiple BarrelDB nodes connected via Raft. For now, gonna enjoy some chai and release this project to the WWW :)&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Logging on Nomad with Vector</title>
        <published>2022-09-04T00:10:55+05:30</published>
        <updated>2022-09-04T00:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/nomad-logging/"/>
        <id>https://mrkaran.dev/posts/nomad-logging/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/nomad-logging/">&lt;p&gt;Application orchestrators like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;&quot;&gt;Nomad&lt;&#x2F;a&gt;, Kubernetes etc., allow you to deploy multiple applications on the same host. Logs are stored on the underlying node wherever the applications are run. However, it’s pretty common to treat these instances as ephemeral if they’re a part of an autoscaling group. Therefore depending on the node’s availability to search these logs is not a practical idea as the node can go down anytime. Moreover, in most cases, access to these nodes is limited to cluster administrators, not the maintainers (developers&#x2F;application owners). In such cases, a &lt;em&gt;log shipping&lt;&#x2F;em&gt; agent must ship and aggregate logs from all cluster nodes and store them centrally (like Elasticsearch, Clickhouse, Loki).&lt;&#x2F;p&gt;
&lt;p&gt;I’d recommend reading this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atodorov.me&#x2F;2021&#x2F;07&#x2F;09&#x2F;logging-on-nomad-and-log-aggregation-with-loki&#x2F;&quot;&gt;excellent post&lt;&#x2F;a&gt; by Adrian, who has explained how to set up a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;&quot;&gt;Vector&lt;&#x2F;a&gt; logging pipeline for applications running with &lt;code&gt;docker&lt;&#x2F;code&gt; task driver and ship the logs to Loki. For the applications running using &lt;code&gt;docker&lt;&#x2F;code&gt; task driver, Nomad &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;drivers&#x2F;docker#config-1&quot;&gt;piggybacks&lt;&#x2F;a&gt; to docker daemon for configuring logging options. Docker daemon supports many logging options; in my experience, the &lt;code&gt;journald&lt;&#x2F;code&gt; log driver works reliably well.&lt;&#x2F;p&gt;
&lt;p&gt;However, this post is about tasks not using &lt;code&gt;docker&lt;&#x2F;code&gt; but any other driver (e.g. &lt;code&gt;raw_exec&lt;&#x2F;code&gt; and &lt;code&gt;exec&lt;&#x2F;code&gt;). Nomad doesn’t provide many configuration options for logging for these drivers. The biggest issue is that Nomad logs the application’s &lt;code&gt;stdio&#x2F;stderr&lt;&#x2F;code&gt; stream to the log directory &lt;em&gt;as-is&lt;&#x2F;em&gt; without annotating any metadata about the task. This means that if you’ve multiple applications running on one host, the log shipping agent will not be able to &lt;em&gt;identify&lt;&#x2F;em&gt; which application’s logs are being ingested.&lt;&#x2F;p&gt;
&lt;p&gt;Consider this as an example. We’re running a simple web server using &lt;code&gt;exec&lt;&#x2F;code&gt; driver:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;http&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  datacenters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dc1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bridge&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;python-http&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8888&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;server&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;python3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        args&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;http.server&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8888&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once the alloc is running, we can find its IP address using:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; alloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 1d05d64b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Allocation Addresses&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Allocation&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Addresses&lt;&#x2F;span&gt;&lt;span&gt; (mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bridge&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Label&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         Dynamic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;python-http  yes      192.168.29.76:31775 -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; 8888&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On sending an HTTP request using &lt;code&gt;cURL&lt;&#x2F;code&gt; we can see the logs that this webserver generated:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 192.168.29.76:31775&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;HTTP&#x2F;1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; OK&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; SimpleHTTP&#x2F;0.6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Python&#x2F;3.10.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Sun,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 04&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Sep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2022&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 06:18:45&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; GMT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Content-type:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; text&#x2F;html&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; charset&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Content-Length:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 869&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nomad stores the logs inside the applications’ allocation directory, inside &lt;code&gt;&#x2F;opt&#x2F;nomad&#x2F;data&#x2F;alloc&lt;&#x2F;code&gt;. To see the logs for the above allocation ID, we can use:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tail -f &#x2F;opt&#x2F;nomad&#x2F;data&#x2F;alloc&#x2F;1d05d64b-4b59-3c65-8261-760499d9e4f6&#x2F;alloc&#x2F;logs&#x2F;server.stderr.0tail -f server.stderr.0 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;192.168.29.76 - - [04&#x2F;Sep&#x2F;2022 11:48:26] &amp;quot;GET &#x2F; HTTP&#x2F;1.1&amp;quot; 200 -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;192.168.29.76 - - [04&#x2F;Sep&#x2F;2022 11:48:45] &amp;quot;GET &#x2F; HTTP&#x2F;1.1&amp;quot; 200 -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;enriching-logs-with-metadata&quot;&gt;Enriching logs with metadata&lt;a class=&quot;zola-anchor&quot; href=&quot;#enriching-logs-with-metadata&quot; aria-label=&quot;Anchor link for: enriching-logs-with-metadata&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As you can see, these logs are precisely what the &lt;code&gt;python3 -m http.server&lt;&#x2F;code&gt; command generates. Ideally, Nomad should have enriched these logs with metadata about the allocation ID, job name, namespace, the node it’s running on, etc., as noted in this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;10219&quot;&gt;GitHub issue&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;However, since that’s not yet available, I brainstormed a few different options:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;approach-1-sidecar&quot;&gt;Approach 1: Sidecar&lt;a class=&quot;zola-anchor&quot; href=&quot;#approach-1-sidecar&quot; aria-label=&quot;Anchor link for: approach-1-sidecar&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The first approach was to run &lt;code&gt;vector&lt;&#x2F;code&gt; as a sidecar next to the main task. This is the simplest option, to begin with. Vector can be independently configured to add metadata for the logs collected from the allocation directory of the group. However, as with every sidecar deployment, there’s a lot of extra resource usage. For every 10 different groups, reserving resources for 10 vector agents quickly eats up your available CPU&#x2F;Memory of the underlying node. A more critical downside, though, was asking every developer to also configure a Vector sidecar job. And to keep all these configs in sync to ensure they’re unified across namespaces is also another headache. Due to these reasons, I discarded this option early on. However, suppose your deployment scale (managing applications) is relatively smaller. In that case, this is actually not a bad idea.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;approach-2-events-stream&quot;&gt;Approach 2: Events Stream&lt;a class=&quot;zola-anchor&quot; href=&quot;#approach-2-events-stream&quot; aria-label=&quot;Anchor link for: approach-2-events-stream&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;My next option was to listen to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;api-docs&#x2F;events&quot;&gt;Nomad events stream&lt;&#x2F;a&gt; and generate a “vector” configuration template to collect logs and enrich them with metadata from the Events Stream. I developed v0.1 of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;nomad-vector-logger&quot;&gt;nomad-vector-logger&lt;&#x2F;a&gt; based on this concept. Since I’ve written a wrapper to collect events from Nomad using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;nomad-events-sink&quot;&gt;nomad-events-sink&lt;&#x2F;a&gt; it was relatively straightforward to extend it to generate a &lt;code&gt;vector.toml&lt;&#x2F;code&gt; config. However, after testing in prod for a few days, I noticed that relying on the &lt;code&gt;events&lt;&#x2F;code&gt; stream is unreliable. Nomad events are not WebSocket based (as of yet). It’s a simple long polling mechanism which sends events to a Go channel as and when they happen. What happens when you miss an event? What happens when you run &lt;code&gt;nomad system gc&lt;&#x2F;code&gt;, which clears the events index? These were some of the challenges I faced with this v0.1 approach. There needs to be some sort of “reconcile” mechanism that periodically runs. A reconciliation loop that lists all allocations using the HTTP API can help whenever there are missing events.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;approach-3-enrichment-tables&quot;&gt;Approach 3: Enrichment Tables&lt;a class=&quot;zola-anchor&quot; href=&quot;#approach-3-enrichment-tables&quot; aria-label=&quot;Anchor link for: approach-3-enrichment-tables&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I also posted about the above program in Vector’s discord group (they’re super active+helpful folks) and discussed this daemon with them. They also suggested a simpler alternative: generating a CSV of running allocations instead of a &lt;code&gt;.toml&lt;&#x2F;code&gt; config. Vector has support for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;highlights&#x2F;2021-11-18-csv-enrichment&#x2F;&quot;&gt;Enrichment Tables&lt;&#x2F;a&gt; which means that it can “lookup” a CSV file to find a particular row and enrich the log event with the information found from the CSV. This seemed a super cool idea, and I developed v0.2 using this. Super thankful to Vector maintainers for giving me this idea!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;discord_vector_1.png&quot; alt=&quot;image&quot; &#x2F;&gt;
&lt;img src=&quot;&#x2F;images&#x2F;discord_vector_2.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;However, this approach had a few “subtle” drawbacks that I found:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vector&lt;&#x2F;code&gt; doesn’t support live-reloading if the CSV file changes. &lt;code&gt;vector&lt;&#x2F;code&gt; has support for watching a config file for changes or sending a &lt;code&gt;SIGHUP&lt;&#x2F;code&gt; to reload. However, that only works for vector’s own config files. Since the CSV file is an external file, vector cannot &lt;em&gt;watch&lt;&#x2F;em&gt; it for changes. I came up with an ugly bash script hack and compared the &lt;code&gt;md5&lt;&#x2F;code&gt; hash of the file in a &lt;code&gt;while&lt;&#x2F;code&gt; loop and if it changed, then send a &lt;code&gt;SIGHUP&lt;&#x2F;code&gt; to vector. All I can say is &lt;em&gt;it’s ugly, but it works&lt;&#x2F;em&gt;. If you wish to see it, it’s available &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;nomad-vector-logger&#x2F;blob&#x2F;csv&#x2F;examples&#x2F;deployment.nomad#L124-L151&quot;&gt;here&lt;&#x2F;a&gt; in all it’s glory.&lt;&#x2F;li&gt;
&lt;li&gt;The most significant issue was the chance of losing logs for the initial 10-20s of a new allocation. The above shell script had a &lt;code&gt;sleep(10)&lt;&#x2F;code&gt; because &lt;code&gt;md5sum&lt;&#x2F;code&gt; can be a bit CPU intensive to keep frequently doing. Vector sees a new allocation and starts ingesting events. It tries to look up the CSV row by the allocation ID, but it doesn’t find it &lt;em&gt;yet&lt;&#x2F;em&gt; in the CSV file, complains about it, and drops the log event. Thus, I had to drop the CSV idea in search to find another more reliable approach to this. For people interested in this approach, you can checkout the &lt;code&gt;csv&lt;&#x2F;code&gt; branch &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;nomad-vector-logger&#x2F;tree&#x2F;csv&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;approach-4-periodic-reconciliation-loop&quot;&gt;Approach 4: Periodic Reconciliation Loop&lt;a class=&quot;zola-anchor&quot; href=&quot;#approach-4-periodic-reconciliation-loop&quot; aria-label=&quot;Anchor link for: approach-4-periodic-reconciliation-loop&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The final v0.3.0 solution, which IMHO fixed all the above issues, was:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Skip Nomad events stream. Since I have to build a reconciliation loop anyway, listening to events is just extra work without tangible benefits.&lt;&#x2F;li&gt;
&lt;li&gt;I used a background Goroutine channel to periodically refresh the list of allocations running on that node. Even if I fetched this list once every 30s or so, it’s OK because Vector will start ingesting logs &lt;em&gt;once&lt;&#x2F;em&gt; the config gets generated. It will start reading the file &lt;em&gt;from the beginning&lt;&#x2F;em&gt;. So logs aren’t lost even if I templated the config much later after the alloc began running.&lt;&#x2F;li&gt;
&lt;li&gt;I added the support to &lt;em&gt;delay&lt;&#x2F;em&gt; the removal of allocation from the file. If an allocation is stopped (e.g., a new version is deployed or the job restarted), the program doesn’t &lt;em&gt;immediately&lt;&#x2F;em&gt; removes the allocation from the config file. The user can set a &lt;em&gt;delay&lt;&#x2F;em&gt; period which works like a cooling down period. In this period, one can &lt;em&gt;assume&lt;&#x2F;em&gt; that Vector would have finished sending all logs to the upstream. In case the application generates too many logs faster than what the upstream sink can accept (e.g. if the upstream Elasticsearch gets slower). Suppose we remove the allocation _&lt;em&gt;immediately&lt;&#x2F;em&gt; whenever it stops. In that case, there’s a probability that Vector wouldn’t have read the file to the &lt;em&gt;end&lt;&#x2F;em&gt;. This cooling period helps to ensure that doesn’t happen. This is not a fool-proof situation but should cover most cases unless the upstream sink is dead for many hours.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;how-it-works&quot;&gt;How it works&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-it-works&quot; aria-label=&quot;Anchor link for: how-it-works&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we’ve covered a few different approaches and the pros&#x2F;cons of each let’s see how &lt;code&gt;nomad-vector-logger&lt;&#x2F;code&gt; works. Essentially &lt;code&gt;nomad-vector-logger&lt;&#x2F;code&gt; is meant to be deployed inside a Nomad cluster as a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;schedulers#system&quot;&gt;&lt;code&gt;system&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; job. A system job in Nomad runs on &lt;em&gt;each&lt;&#x2F;em&gt; node. Whenever a new node gets added to the cluster, Nomad’s scheduler schedules a copy of this program on that new node automatically. This is the equivalent of a “Daemonset” in K8s.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;nomad-vector-logger&lt;&#x2F;code&gt; uses Nomad’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;api-docs&quot;&gt;HTTP API&lt;&#x2F;a&gt; to query all nodes’ running allocations. Once it gets the list, it adds it to an internal map and signals to generate a config.&lt;&#x2F;p&gt;
&lt;p&gt;The final config that is templated out looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;source_nomad_alloc_64a2f9fd-e003-0bb3-b5cd-838125283a06_proxy&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;include&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;opt&#x2F;nomad&#x2F;data&#x2F;alloc&#x2F;64a2f9fd-e003-0bb3-b5cd-838125283a06&#x2F;alloc&#x2F;logs&#x2F;proxy*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;line_delimiter&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;read_from&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;beginning&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;transforms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;transform_nomad_alloc_64a2f9fd-e003-0bb3-b5cd-838125283a06_proxy&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;remap&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;source_nomad_alloc_64a2f9fd-e003-0bb3-b5cd-838125283a06_proxy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;source&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;# Store Nomad metadata.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.nomad.namespace = &amp;quot;default&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.nomad.node_name = &amp;quot;pop-os&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.nomad.job_name = &amp;quot;nginx&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.nomad.group_name = &amp;quot;nginx&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.nomad.task_name = &amp;quot;proxy&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.nomad.alloc_id = &amp;quot;64a2f9fd-e003-0bb3-b5cd-838125283a06&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For people unfamiliar with vector, it’s essentially doing 2 things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Get logs from a “file” &lt;em&gt;source&lt;&#x2F;em&gt;. The file path comes from &lt;code&gt;nomad-vector-logger&lt;&#x2F;code&gt; (where all the logs for &lt;code&gt;proxy&lt;&#x2F;code&gt; task are located)&lt;&#x2F;li&gt;
&lt;li&gt;It adds a JSON object &lt;code&gt;nomad&lt;&#x2F;code&gt; with relevant keys.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Vector &lt;em&gt;pipeline&lt;&#x2F;em&gt; will send this event to another “transformer” which can further process the log event (for eg parsing it as &lt;code&gt;logfmt&lt;&#x2F;code&gt; or JSON etc) and then finally send it to an upstream &lt;em&gt;sink&lt;&#x2F;em&gt; like Loki&#x2F;Elasticsearch etc.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s an example of the before&#x2F;after of a log line shown above in this post:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;before&quot;&gt;Before&lt;a class=&quot;zola-anchor&quot; href=&quot;#before&quot; aria-label=&quot;Anchor link for: before&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nginx_raw.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;after&quot;&gt;After&lt;a class=&quot;zola-anchor&quot; href=&quot;#after&quot; aria-label=&quot;Anchor link for: after&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nginx_json.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Perfect! We’ve annotated the same log event with Nomad metadata, and Vector will be able to identify these logs. If you’re interested in a complete setup on deploying this to Nomad, take a look at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;nomad-vector-logger&#x2F;tree&#x2F;main&#x2F;dev&quot;&gt;dev setup&lt;&#x2F;a&gt; which contains a Nomad jobspec to deploy &lt;code&gt;nomad-vector-logger&lt;&#x2F;code&gt; as a sidecar with &lt;code&gt;vector&lt;&#x2F;code&gt; as the main task.&lt;&#x2F;p&gt;
&lt;p&gt;Hope this post helped you start configuring a logging pipeline for applications running with non-docker task drivers.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Don&#x27;t use which</title>
        <published>2022-08-08T00:00:00+05:30</published>
        <updated>2022-08-08T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/stop-which/"/>
        <id>https://mrkaran.dev/posts/stop-which/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/stop-which/">&lt;p&gt;&lt;code&gt;which&lt;&#x2F;code&gt; is a non-standard&#x2F;non-POSIX compliant program. I faced many issues getting &lt;code&gt;which&lt;&#x2F;code&gt; to work in a chroot environment (Nomad).&lt;&#x2F;p&gt;
&lt;p&gt;So basically, &lt;code&gt;which&lt;&#x2F;code&gt; is a simple shell script program to find out the dependency by searching the &lt;code&gt;$PATH&lt;&#x2F;code&gt; (which is what makes it less deterministic). It’s also somehow symlinked 3 levels deep in Debian:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ls&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;laht&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;usr&#x2F;bin&#x2F;which&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;lrwxrwxrwx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 23&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 26&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 22:25&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;usr&#x2F;bin&#x2F;which&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;alternatives&#x2F;which&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ls&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;laht&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;alternatives&#x2F;which&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;lrwxrwxrwx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 26&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 26&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 22:25&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;alternatives&#x2F;which&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;usr&#x2F;bin&#x2F;which.debianutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, notice this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; which&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ls:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; aliased&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ls&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-color=tty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;usr&#x2F;bin&#x2F;which.debianutils&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both are the same programs. However, why is the output different? This is because &lt;code&gt;which&lt;&#x2F;code&gt; is apparently a shell built-in &lt;code&gt;zsh&lt;&#x2F;code&gt;, that is why:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; zsh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;which&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; which&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;which&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; built-in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;which&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; which&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;which&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The inconsistency happens because &lt;code&gt;zsh&lt;&#x2F;code&gt; treats &lt;code&gt;which&lt;&#x2F;code&gt; as a shell built-in when it’s apparently not one.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;874049&#x2F;&quot;&gt;This&lt;&#x2F;a&gt; article has some more details on why &lt;code&gt;which&lt;&#x2F;code&gt; is &lt;em&gt;bad&lt;&#x2F;em&gt; and how the Debian team is slowly deprecating it from being a part of debianutils anymore.&lt;&#x2F;p&gt;
&lt;p&gt;When I invoked &lt;code&gt;which&lt;&#x2F;code&gt; from inside a Nomad chroot, it complained that I didn’t have &lt;code&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;code&gt; (because I was using a custom chroot mount). I started looking hard for alternatives because this silly utility already wasted too much of my time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-to-use&quot;&gt;What to use&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-to-use&quot; aria-label=&quot;Anchor link for: what-to-use&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Use &lt;code&gt;command -v&lt;&#x2F;code&gt;. It’s a shell built-in, so it avoids a dependency on an external binary (unlike &lt;code&gt;which&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;usage-example&quot;&gt;Usage example:&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage-example&quot; aria-label=&quot;Anchor link for: usage-example&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; !&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Can&amp;#39;t find &amp;#39;aws&amp;#39; executable. Aborted.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;fi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;references&quot;&gt;References&lt;a class=&quot;zola-anchor&quot; href=&quot;#references&quot; aria-label=&quot;Anchor link for: references&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I found the following posts while digging &lt;code&gt;which&lt;&#x2F;code&gt; and its alternatives.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hynek.me&#x2F;til&#x2F;which-not-posix&#x2F;&quot;&gt;which-not-posix&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;questions&#x2F;85249&#x2F;why-not-use-which-what-to-use-then&quot;&gt;why-not-use-which-what-to-use-then&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Fin&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Attending IndiaFOSS 2022</title>
        <published>2022-08-07T00:00:00+05:30</published>
        <updated>2022-08-07T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/indiafoss-2022/"/>
        <id>https://mrkaran.dev/posts/indiafoss-2022/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/indiafoss-2022/">&lt;p&gt;On June 28, I received a text from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;anandology.com&#x2F;&quot;&gt;Anand&lt;&#x2F;a&gt; nudging me to submit a CFP for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;indiafoss.net&#x2F;&quot;&gt;IndiaFOSS&lt;&#x2F;a&gt;. Until then, I’d not planned to attend IndiaFOSS because travelling to participate in a conference didn’t seem enticing. However, the thought of visiting Bangalore (a city where I spent five years before Covid took the joy from our lives) stayed in my mind for the rest of the day. Call it serendipity or just that little external motivation by Anand; I decided to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;indiafoss.net&#x2F;2022&#x2F;cfp&#x2F;submissions&#x2F;self-hosting-applications-with-nomad&quot;&gt;submit a proposal&lt;&#x2F;a&gt; on Self Hosting with Nomad. IndiaFOSS would be the first physical conference I would attend after the pandemic. I love attending conferences because you get to meet and interact with many people (I somehow dislike the term “networking with people” because it’s heavily connoted with marketing&#x2F;sales pitches).&lt;&#x2F;p&gt;
&lt;p&gt;IndiaFOSS is a v2 of a small pilot conference &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;indiaos.in&#x2F;&quot;&gt;IndiaOS&lt;&#x2F;a&gt; that happened in 2020. Around 650 people attended IndiaFOSS, and the execution scale was much bigger this time. IndiaFOSS is a 100% volunteer-driven conference, yet everything was quite professionally managed. My friend &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dhirajbalakrishnan.dev&#x2F;&quot;&gt;Dhiraj&lt;&#x2F;a&gt; travelled from Chennai to attend the conference, and I hung out with him for most of the next two days.&lt;&#x2F;p&gt;
&lt;p&gt;Filling our tummies with a scrumptious breakfast of &lt;em&gt;Thatte Idlis&lt;&#x2F;em&gt;, we headed to attend the keynote by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;rushabh_mehta&quot;&gt;Rushabh&lt;&#x2F;a&gt;, who gave an excellent overview of FOSS United and its journey so far. There were a series of exciting talks right after - especially by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kovidgoyal.net&#x2F;&quot;&gt;Kovid&lt;&#x2F;a&gt;, a prolific FOSS contributor from India. Kovid’s software is widely used across the globe. He shared the story of how &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calibre-ebook.com&#x2F;&quot;&gt;calibre&lt;&#x2F;a&gt; evolved from a bunch of scripts written to get around Sony’s DRM to become the most sought-after ebook management tool that it is now. I’ve myself used calibre in one of my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;webkin&quot;&gt;initial projects&lt;&#x2F;a&gt;(back when I was still learning Python, please don’t judge that codebase). Next was the much-awaited interview of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;about.ruds.io&#x2F;&quot;&gt;Rudra Saraswat&lt;&#x2F;a&gt; - the 12-year-old &lt;em&gt;whiz kid&lt;&#x2F;em&gt; who’s a primary contributor to Ubuntu Unity Remix and many other projects. The entire auditorium was stunned to witness how this bright young kid manages his studies, extra-curricular and FOSS projects with a laser-sharp focus.&lt;&#x2F;p&gt;
&lt;p&gt;I spent some time reviewing my slides which were scheduled right after an excellent talk on hpw the Kubernetes release team works -  by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nabarun.dev&#x2F;&quot;&gt;Nabarun&lt;&#x2F;a&gt;. I was pleasantly surprised to see many people interested in Self Hosting&#x2F;Nomad. You can check out the slides &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;talks&#x2F;self-hosting-nomad-indiafoss.html&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It was time for lunch, and I finally got to meet &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.vinayakhegde.com&#x2F;&quot;&gt;Vinayak&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bibhasdn.com&#x2F;&quot;&gt;Bibhas&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.chaturvedi.me&#x2F;&quot;&gt;Gaurav&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.raghavmalawat.com&#x2F;&quot;&gt;Raghav&lt;&#x2F;a&gt; with whom I’ve been interacting in a small Discord group since so many months! This is what pandemic years took away from us, sigh!&lt;&#x2F;p&gt;
&lt;p&gt;After lunch, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nadh.in&#x2F;&quot;&gt;Kailash&lt;&#x2F;a&gt; presented his fantastic talk on languages, dictionaries, and his FOSS project - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;knadh&#x2F;dictpress&quot;&gt;dictpress&lt;&#x2F;a&gt;. Kailash was anticipating that people would be drowsy after lunch, but I doubt anyone would want to miss this talk. He gave a glimpse of the monumental work done by Datuk KJ Joseph and V. Krishna in the field of dictionaries and how dictpress makes it easier for anyone to host a dictionary website for any language.&lt;&#x2F;p&gt;
&lt;p&gt;The rest of the day was spent hanging out in the lobby, meeting fellow &lt;em&gt;hackers&lt;&#x2F;em&gt;, and chit-chatting. I consider myself an introvert, but I guess with developers, I tend to speak up openly because we tend to ignore any small-talks :P. Rainy evenings and a weekend meant all the &lt;em&gt;Peak Bengaluru&lt;&#x2F;em&gt; memes about not finding cabs were experienced first-hand.&lt;&#x2F;p&gt;
&lt;p&gt;Day 2 had quite a good lineup of talks as well. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;KThakkannavar&quot;&gt;Krutika&lt;&#x2F;a&gt; shared the designer’s dilemma of contributing to FOSS Projects. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;captnemo.in&#x2F;&quot;&gt;Nemo&lt;&#x2F;a&gt; talked about how we could get a FOSS UPI app and touched upon the openness of UPI. We even did an open space around Self Hosting where many of us self-hosted enthusiasts came together and discussed different topics&#x2F;problems we encountered while self-hosting. It was my first time interacting with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;abhas.io&#x2F;&quot;&gt;Abhas&lt;&#x2F;a&gt;, who runs &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deeproot.in&#x2F;&quot;&gt;Deeproot Linux&lt;&#x2F;a&gt;. He shared his wisdom and experiences from self-hosting email servers, media servers and just about anything. I was pretty motivated by his dedication.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The best part about IndiaFOSS was that this wasn’t a conference meant just for techies. The talks highlighted every domain of FOSS- policy, design, languages, and hardware rather than just keeping it limited to software. I was happy to see a conference not peddled with any “corporate” product talks. This is what all FOSS conferences should look like, I guess?&lt;&#x2F;p&gt;
&lt;p&gt;I look forward to attending (and hopefully volunteering) next year’s conference!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;indiafoss_2022.jpeg&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fin&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Debugging DNS Issues in Nomad</title>
        <published>2022-07-14T00:00:00+05:30</published>
        <updated>2022-07-14T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/dns-nomad/"/>
        <id>https://mrkaran.dev/posts/dns-nomad/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/dns-nomad/">&lt;p&gt;At work, my colleagues and I stumbled upon a hair-pulling networking issue involving a specific problem when connecting to a Kafka cluster. We use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;twmb&#x2F;franz-go&quot;&gt;franz-go&lt;&#x2F;a&gt; library in our Golang applications to interact with an external Kafka cluster. These Go apps are hosted inside a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;&quot;&gt;Nomad&lt;&#x2F;a&gt; cluster and running with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;drivers&#x2F;exec&quot;&gt;exec&lt;&#x2F;a&gt; driver.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-issue&quot;&gt;The Issue&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-issue&quot; aria-label=&quot;Anchor link for: the-issue&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Solving issues where a specific condition happens &lt;em&gt;only&lt;&#x2F;em&gt; sometimes is terribly difficult to debug because you need to reproduce the bug in a controlled environment. Our issue was that writing the &lt;strong&gt;first&lt;&#x2F;strong&gt; message to a Kafka topic took unusually high time (&amp;gt;5 seconds) while the writes of subsequent messages were instant. The following messages were instant for the next 30s, and then the write again took &amp;gt;5s.&lt;&#x2F;p&gt;
&lt;p&gt;The request flow looks something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Go app in Nomad cluster (bridge mode) -&amp;gt; Kafka node in a Kafka cluster&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Both apps are inside the same VPC running on AWS EC2 instances. The Nomad task is running with &lt;code&gt;network.mode=bridge&lt;&#x2F;code&gt;, which means that there are some &lt;code&gt;iptables&lt;&#x2F;code&gt; rules configured to do SNAT&#x2F;DNAT translation to forward packets from the default bridge network (&lt;code&gt;nomad&lt;&#x2F;code&gt;) to the default ethernet interface (&lt;code&gt;ens5&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;We have a couple of other Nomad clusters in our environment and regularly use external EC2 instances to communicate, and we’ve never observed any slowdowns in our existing applications. This behaviour seemed something specific to Kafka. However, we discovered that we could not reproduce the high wait time issue in Kafka when the message was sent from a task running as &lt;em&gt;host&lt;&#x2F;em&gt; mode. So now, we had two conflicting things which made this issue strange:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Issue happens in &lt;code&gt;bridge&lt;&#x2F;code&gt; mode, not in &lt;code&gt;host&lt;&#x2F;code&gt; mode.&lt;&#x2F;li&gt;
&lt;li&gt;Issue happens only with Kafka nodes, not with any external services - even in bridge mode.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We spent a lot of time dissecting our apps, turning on &lt;code&gt;TRACE&lt;&#x2F;code&gt; level logging for Kafka clusters and enabling debug mode in &lt;code&gt;franz-go&lt;&#x2F;code&gt;. One of the significant challenges for us was that even an idle Kafka cluster could be super &lt;strong&gt;chatty&lt;&#x2F;strong&gt;, producing ~1Mn records for a few minutes when run with &lt;code&gt;TRACE&lt;&#x2F;code&gt;. Cutting through the noise and finding the exact point where the slowdown happened turned out to be more difficult than expected.&lt;&#x2F;p&gt;
&lt;p&gt;However, with the debug logs in &lt;code&gt;franz-go&lt;&#x2F;code&gt;, we’d arrived at a breakthrough which helped us narrow down the issue. We saw the &lt;code&gt;write_wait&lt;&#x2F;code&gt; time to be ~5s in the logs &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;twmb&#x2F;franz-go&#x2F;blob&#x2F;6c87885d13a36dfadd42ffa2c2c58cb81646a93a&#x2F;pkg&#x2F;kgo&#x2F;broker.go#L969&quot;&gt;emitted&lt;&#x2F;a&gt; by &lt;code&gt;franz-go&lt;&#x2F;code&gt;. The subsequent messages had &lt;code&gt;write_wait&lt;&#x2F;code&gt; as low as a few microseconds. What was puzzling was why Kafka took so much time to wait before writing the bytes to the underlying socket.&lt;&#x2F;p&gt;
&lt;p&gt;We forked the franz-go library and added a bunch of our custom logs to figure out where and why exactly the slowdown happens. One issue in the logs emitted by franz-go was that no timestamps were attached to the logger. We added that and deployed the binaries with the patched version. This time we immediately found the logs, which pointed that it took ~5s from the time it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;twmb&#x2F;franz-go&#x2F;blob&#x2F;6c87885d13a36dfadd42ffa2c2c58cb81646a93a&#x2F;pkg&#x2F;kgo&#x2F;broker.go#L570&quot;&gt;initiated the connection&lt;&#x2F;a&gt; to the Kafka broker node and the time it was able to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;twmb&#x2F;franz-go&#x2F;blob&#x2F;6c87885d13a36dfadd42ffa2c2c58cb81646a93a&#x2F;pkg&#x2F;kgo&#x2F;broker.go#L570&quot;&gt;connect to the node&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-fix&quot;&gt;The Fix&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-fix&quot; aria-label=&quot;Anchor link for: the-fix&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The node’s address was an internal hostname &lt;code&gt;kafka-abc.private-zone.internal&lt;&#x2F;code&gt;. We postulated that it could be a DNS resolver issue. We did a &lt;code&gt;dig kafka-abc.private-zone.internal&lt;&#x2F;code&gt; and instantly got the record. Maybe it’s cached? We decided to verify the &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; till we waited for the TTL of the record to expire. Opening this seemingly innocent &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; revealed what the issue was DNS indeed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nameserver bad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nameserver good&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We had an &lt;em&gt;unreachable&lt;&#x2F;em&gt; nameserver address in the &lt;code&gt;nameserver&lt;&#x2F;code&gt; list. The first message has ~5s write timeout because &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; has a 5s default timeout in case the nameserver is unreachable. Go’s DNS resolver picked up the second resolver, which cached the DNS records until the record’s TTL (30 seconds). Subsequent Kafka write messages on the topic worked without any issues in the TTL window. When the DNS record expires, rinse, and repeat. We later found the source of the bad nameserver came from our Nomad client initialising script.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;a class=&quot;zola-anchor&quot; href=&quot;#takeaways&quot; aria-label=&quot;Anchor link for: takeaways&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We use a custom Nomad client initialising script in our Nomad clusters to populate the &lt;code&gt;chroot_env&lt;&#x2F;code&gt;. Since, by default, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;drivers&#x2F;exec#chroot&quot;&gt;chroot&lt;&#x2F;a&gt; provided by Nomad copies the&lt;code&gt;&#x2F;usr&lt;&#x2F;code&gt;&#x2F; directory, we found that it increased the initial startup time of the alloc. It made sense to customise the &lt;code&gt;chroot_env&lt;&#x2F;code&gt; with the list of binaries and config files we would need.&lt;&#x2F;p&gt;
&lt;p&gt;One of the configs happens to be &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt;, which DNS resolvers use to resolve queries. On the host, we have &lt;code&gt;systemd-resolve&lt;&#x2F;code&gt; running and &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; is configured with the stub resolver address. However, since that address (&lt;code&gt;127.0.0.53&lt;&#x2F;code&gt;) is unreachable by the &lt;em&gt;bridge&lt;&#x2F;em&gt; network in Nomad, we mount our custom config, which looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nameserver 10.100.0.2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;options edns0 trust-ad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;search ap-south-1.compute.internal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;nameserver&lt;&#x2F;code&gt; represents the AWS R53 resolver running in all VPCs if configured with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;vpc-dns.html&quot;&gt;enableDnsSupport&lt;&#x2F;a&gt; in VPC settings.&lt;&#x2F;p&gt;
&lt;p&gt;The above config ensures that all DNS queries for the tasks inside the bridge network go directly to the AWS R53 resolver. The resolver can do DNS Lookups for the private zones associated with the R53 in that VPC and forward all other hostnames to their own upstream DNS resolver.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fun-fact&quot;&gt;Fun Fact&lt;a class=&quot;zola-anchor&quot; href=&quot;#fun-fact&quot; aria-label=&quot;Anchor link for: fun-fact&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you don’t mount a custom &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt;, then DNS resolution is broken by default in any Nomad exec task. You can quickly reproduce it with this task definition:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;sleep&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  datacenters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dc1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;sleep&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;sleep&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bash&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        args&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;sleep infinity&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Run a Nomad agent in &lt;code&gt;-dev&lt;&#x2F;code&gt; mode:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sleep.nomad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When you exec inside the alloc:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; alloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sleep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 8b4a0a82&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;resolv.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nameserver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 127.0.0.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; communications&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 127.0.0.1#53:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; refused&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I believe Nomad should bootstrap some DNS resolver or a relevant &lt;code&gt;iptables&lt;&#x2F;code&gt; rule for the exec tasks so that DNS can be resolved by default without the need to mount a custom config. For comparison, a &lt;code&gt;docker&lt;&#x2F;code&gt; also bootstraps the container with a customisable &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt;, and the settings can be specified either at runtime and fallback to the global settings in &lt;code&gt;&#x2F;etc&#x2F;docker&#x2F;daemon.json&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I hope this post helps someone solve these weird DNS issues when running tasks with the bridge network and exec task driver in the Nomad cluster.&lt;&#x2F;p&gt;
&lt;p&gt;Like they say:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;haiku-dns.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Understanding Networking in Nomad</title>
        <published>2022-05-14T00:10:55+05:30</published>
        <updated>2022-05-14T00:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/nomad-networking-explained/"/>
        <id>https://mrkaran.dev/posts/nomad-networking-explained/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/nomad-networking-explained/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;&quot;&gt;Nomad&lt;&#x2F;a&gt; is a general-purpose cluster orchestrator and scheduler. Up until &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.hashicorp.com&#x2F;blog&#x2F;nomad-1-3-adds-native-service-discovery-and-edge-workload-support&quot;&gt;Nomad 1.3&lt;&#x2F;a&gt; was released, it had no native support for discovering other applications running in the cluster. This is sort of a very elementary requirement when scheduling tasks in a cluster. Nomad relies on Consul to discover other “services” and has first class support for registering and fetching service records which makes things easier. Consul provides the records via various mechanisms such as a REST API, DNS and Consul Templates which render the exact IP&#x2F;Port of the service in a Go template that can be injected into your application.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been using Nomad since quite some time (both at work and for my self hosted instance) however I’ve often tripped when it comes to Networking. Nomad has a lot of simple concepts and it all “clicks” once you understand and recognise various patterns that can be used to connect the applications. A major learning curve for someone new to Nomad and trying to integrate Consul is that the person now has to first understand how Consul works, deploy a Consul cluster and this creates a lot of friction amongst newcomers to Nomad. Nomad 1.3 solves a part of this issue (i.e. no need to run Consul for basic service discovery) and is a great fit for just getting started with Nomad based networking. However, in this post I’d like to go through all the different networking patterns I’ve known or used in production and make an attempt at simplifying these concepts for Nomad beginners.&lt;&#x2F;p&gt;
&lt;p class=&quot;ad-info&quot;&gt;
I&#x27;ll be running a single node Nomad on my dev machine. The instructions to do that can be seen &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;mr-karan&#x2F;b1bb4f65ae31d91985e6a64451b79f6e&quot;&gt;here&lt;&#x2F;a&gt;.
&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scenario-1-expose-an-application-on-the-host&quot;&gt;Scenario 1: Expose an application on the host&lt;a class=&quot;zola-anchor&quot; href=&quot;#scenario-1-expose-an-application-on-the-host&quot; aria-label=&quot;Anchor link for: scenario-1-expose-an-application-on-the-host&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad_redis_dyn_port_illus.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We’ll start off with the simplest usecase: You have a &lt;code&gt;redis&lt;&#x2F;code&gt; container and you want to expose that to the host. The &lt;code&gt;docker run&lt;&#x2F;code&gt; equivalent to what we wanna do is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p=6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis:7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This command exposes a dynamic port on your host. To see what exactly is the port number, you can do &lt;code&gt;docker ps&lt;&#x2F;code&gt; and find out an output similar to &lt;code&gt;0.0.0.0:49153-&amp;gt;6379&#x2F;tcp&lt;&#x2F;code&gt; under &lt;code&gt;PORTS&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To verify, I can use &lt;code&gt;redis-cli&lt;&#x2F;code&gt; to connect to this host:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis-cli&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 49153&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;127.0.0.1:49153&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ping&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PONG&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fantastic! Now, let’s stop this container and see how we can do the same in Nomad.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  datacenters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dc1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis:7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a barebones definition of how to run Redis on Nomad. We’re not dealing with any volume mounts, custom config etc here - the idea is to only learn networking concepts in Nomad!&lt;&#x2F;p&gt;
&lt;p&gt;Save the above file as &lt;code&gt;job.nomad&lt;&#x2F;code&gt; and deploy to the cluster with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; job.nomad&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Within a few lines of config, we have a Docker container running, which exposes a dynamic port &lt;code&gt;23522&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad_redis_dynamic_port.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can connect to it via &lt;code&gt;redis-cli&lt;&#x2F;code&gt; on our host:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis-cli&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 23522&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;127.0.0.1:23522&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ping&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PONG&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;NOTE: It’s important to have &lt;code&gt;ports&lt;&#x2F;code&gt; in your &lt;code&gt;task.config&lt;&#x2F;code&gt; section. Nomad passes this information to the &lt;code&gt;docker&lt;&#x2F;code&gt; daemon running on the host. So unless you specify which ports to advertise in the container, it won’t know whether to expose 6379 or not.&lt;&#x2F;p&gt;
&lt;p&gt;This can be easily verified with &lt;code&gt;docker inspect&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; without `ports`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; inspect&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fc32a4ffd148&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{json .NetworkSettings.Ports }}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;6379&#x2F;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; with `ports`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; inspect&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0421101d0228&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{json .NetworkSettings.Ports }}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;6379&#x2F;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;HostIp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;HostPort&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;31930&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;6379&#x2F;udp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;HostIp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;HostPort&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;31930&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;exposing-static-ports&quot;&gt;Exposing Static ports&lt;a class=&quot;zola-anchor&quot; href=&quot;#exposing-static-ports&quot; aria-label=&quot;Anchor link for: exposing-static-ports&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A less common scenario is to bind an application to a static port on the host. We’ll cover an example of when you want to do that a bit later, but this is generally not widely used because in a cluster your application can “float” around and the idea of sticking to a port is not useful. However, there’s a way for us to do that by simply adding a &lt;code&gt;static&lt;&#x2F;code&gt; line in our &lt;code&gt;port&lt;&#x2F;code&gt; block:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad_redis_static_port.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When we deploy the same file again, we can see the port allocation has changed from dynamic to the static port we assigned. It’s your job to ensure no other applications are listening on that same interface and port because that’s bound to cause conflicts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scenario-2-communicate-to-redis-within-the-same-group&quot;&gt;Scenario 2: Communicate to Redis within the same group&lt;a class=&quot;zola-anchor&quot; href=&quot;#scenario-2-communicate-to-redis-within-the-same-group&quot; aria-label=&quot;Anchor link for: scenario-2-communicate-to-redis-within-the-same-group&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For this scenario, we are going to assume there’s a Go application that needs to talk to Redis. However, in this scenario, the Redis is sort of like an ephemeral cache, so it’s okay to deploy both of them in the same &lt;em&gt;Task Group&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p class=&quot;ad-info&quot;&gt;
If you don&#x27;t know the difference between a Task and Group, here&#x27;s a very primitive explanation but please read the docs for more clarity.
&lt;br&#x2F;&gt;&lt;br&#x2F;&gt;
A Group can contain multiple tasks. What&#x27;s important to know here is that a group will always have its own shared network namespace. This means, that if you have 2 tasks in the group, they both will have access to the same network namespace. This allows both tasks to talk to each other on the same network interface.
&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  datacenters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dc1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        network_mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis:7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      env&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        DEMO_REDIS_ADDR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;NOMAD_ADDR_redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        network_mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran&#x2F;hello-app:1.0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 512&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Key Points&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You can see we have defined &lt;code&gt;task&lt;&#x2F;code&gt; app and task &lt;code&gt;redis&lt;&#x2F;code&gt; under the same group, &lt;code&gt;app&lt;&#x2F;code&gt;. This means that Nomad will co-locate both of these tasks on the same client (because they tend to share not just the same network namespace but a common allocation directory as well - which makes it super easy to share files across tasks).&lt;&#x2F;li&gt;
&lt;li&gt;We are using &lt;code&gt;NOMAD_ADDR_redis&lt;&#x2F;code&gt; to get the IP:Port combination for the &lt;code&gt;redis&lt;&#x2F;code&gt; task. This gets injected at runtime by Nomad. You can find a list of runtime variables &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;runtime&#x2F;environment&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;This is ideal for quick tests&#x2F;dev setup where you don’t want the overhang of Service Discovery etc and want to connect to your applications in the least friction possible.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The above config is suitable if you’re migrating from &lt;code&gt;docker-compose&lt;&#x2F;code&gt; based environments, you can use this template for your services. The biggest limitation of this approach is that it’s using a host network so it’s not possible to set up any kind of Access Controls on it. This effectively means that nothing prevents any other application on the cluster to talk to these ports.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scenario-3-communicate-across-different-groups&quot;&gt;Scenario 3: Communicate across different groups&lt;a class=&quot;zola-anchor&quot; href=&quot;#scenario-3-communicate-across-different-groups&quot; aria-label=&quot;Anchor link for: scenario-3-communicate-across-different-groups&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Task Groups are useful if you have &lt;em&gt;related&lt;&#x2F;em&gt; tasks (like the init task where you wanna fetch the files before the task starts). But a drawback of using &lt;code&gt;group&lt;&#x2F;code&gt; is that you can’t scale the tasks independently. In the above example, we placed Redis and App in the same group, but that means if you increase &lt;code&gt;count&lt;&#x2F;code&gt; of same group to scale the app, you end up scaling Redis containers too. This is undesirable as Redis may not to scale proportionally to app.&lt;&#x2F;p&gt;
&lt;p&gt;The way to do create multiple groups is to split the tasks into their own individual groups:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  datacenters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dc1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      env&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        DEMO_REDIS_ADDR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;localhost:6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran&#x2F;hello-app:1.0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 512&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis:7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When you submit this job, you get 2 allocation IDs (each group creates one &lt;code&gt;alloc&lt;&#x2F;code&gt;). The key point here is that both of these groups have their own network namespace. So, we don’t really have any way to reach the other application (we can’t really rely on the host network, because there’s no guarantee that both of these groups will be deployed on the same node).&lt;&#x2F;p&gt;
&lt;p&gt;In the previous example, we saw how Nomad exposes runtime variables that contained information about all tasks in other groups. But now since the groups are separate, the &lt;code&gt;app&lt;&#x2F;code&gt; container has no idea about &lt;code&gt;redis&lt;&#x2F;code&gt; (or vice-versa):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; NOMAD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_REGION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_CPU_LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_IP_app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_JOB_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_TASK_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_SECRETS_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_CPU_CORES&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_NAMESPACE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_ALLOC_INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_ALLOC_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_JOB_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_HOST_IP_app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_SHORT_ALLOC_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_DC&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_ALLOC_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_PORT_app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_GROUP_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_PARENT_CGROUP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_TASK_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_HOST_PORT_app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_MEMORY_LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_ADDR_app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_ALLOC_PORT_app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_ALLOC_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOMAD_HOST_ADDR_app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;service-discovery&quot;&gt;Service Discovery&lt;a class=&quot;zola-anchor&quot; href=&quot;#service-discovery&quot; aria-label=&quot;Anchor link for: service-discovery&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is where things get interesting. The &lt;code&gt;app&lt;&#x2F;code&gt; group needs to &lt;em&gt;discover&lt;&#x2F;em&gt; &lt;code&gt;redis&lt;&#x2F;code&gt; before connecting to it. There are multiple ways to do that, but we’ll cover 2 standard ways which are more common.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-nomad-native-service-discovery&quot;&gt;Using Nomad native service discovery&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-nomad-native-service-discovery&quot; aria-label=&quot;Anchor link for: using-nomad-native-service-discovery&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad_networking_inter_group_native.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is a feature launched in Nomad 1.3. Up until this release, Nomad had to rely on Consul for this. But with native service discovery built in Nomad, things are much simpler. Let’s make the following changes to our job file. In each group, we’ll add a &lt;code&gt;service&lt;&#x2F;code&gt; definition:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      provider&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; task is the same&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  group&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      provider&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; task is the same&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, we added a new &lt;code&gt;service&lt;&#x2F;code&gt; block and got rid of &lt;code&gt;static&lt;&#x2F;code&gt; ports. Well, there’s no need to bind to static ports when we’re using service discovery.&lt;&#x2F;p&gt;
&lt;p&gt;After submitting the job, we can use the &lt;code&gt;nomad service list&lt;&#x2F;code&gt; command to ensure the services are registered with Nomad.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; list&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Tags&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;           [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span&gt;         [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To find out details about a particular service, we can use &lt;code&gt;nomad service info&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; info&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          Tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Node&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Alloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   127.0.0.1:29948&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span&gt;]    d92224a5  5f2ac51f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; info&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          Tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Node&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Alloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   127.0.0.1:22300&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span&gt;]    d92224a5  8078c9a6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! We can see the dynamic port assignment in each of the services. To use this config in our app, we will template it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      template&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ range nomadService &amp;quot;redis&amp;quot; }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;DEMO_REDIS_ADDR={{ .Address }}:{{ .Port }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ end }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        destination&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;secrets&#x2F;config.env&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        env&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;         =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran&#x2F;hello-app:1.0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      resources&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 512&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We added the &lt;code&gt;template&lt;&#x2F;code&gt; stanza which will interpolate the env variables in the container. We loop over &lt;code&gt;nomadService&lt;&#x2F;code&gt; and get the address and port of the &lt;code&gt;redis&lt;&#x2F;code&gt; service. This makes it convenient for tasks on other nodes to discover each other.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-consul-service-discovery&quot;&gt;Using Consul Service Discovery&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-consul-service-discovery&quot; aria-label=&quot;Anchor link for: using-consul-service-discovery&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad_networking_inter_group_consul.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Just by tweaking &lt;code&gt;provider&lt;&#x2F;code&gt; in our &lt;code&gt;service&lt;&#x2F;code&gt; block, we can use the Consul agent for service discovery.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      provider&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;consul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      template&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ range service &amp;quot;redis&amp;quot; }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;DEMO_REDIS_ADDR={{ .Address }}:{{ .Port }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ end }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;p class=&quot;ad-info&quot;&gt;
Ensure that you&#x27;re running Consul and have connected Nomad to it. Please refer to &lt;a href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;integrations&#x2F;consul-integration&quot;&gt;docs&lt;&#x2F;a&gt; for the same.
&lt;&#x2F;p&gt;
&lt;p&gt;Since now we are using &lt;code&gt;consul&lt;&#x2F;code&gt; for registering services, we have to loop over &lt;code&gt;service&lt;&#x2F;code&gt; instead of &lt;code&gt;nomadService&lt;&#x2F;code&gt;. The rest of the things remain pretty much the same. I really like how with just 2 lines of code you can switch between Nomad&#x2F;Consul for discovering services.&lt;&#x2F;p&gt;
&lt;p&gt;Now, of course, there are certain &lt;strong&gt;advantages&lt;&#x2F;strong&gt; to using Consul:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You can query the address of the service with DNS:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;doggo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.service.consul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; @tcp:&#x2F;&#x2F;127.0.0.1:8600&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    TYPE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    CLASS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   TTL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ADDRESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     NAMESERVER&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;redis.service.consul.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      0s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  172.20.10.3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 127.0.0.1:8600&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Define health checks. Since it’s a new feature, health checks on Nomad service aren’t there but there’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;12576&quot;&gt;GitHub issue&lt;&#x2F;a&gt; open for the same.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update (2024)&lt;&#x2F;strong&gt;: Native health checks are now available in Nomad since version 1.4 (released October 2022). This means you can define health checks directly in your Nomad service definitions without requiring Consul. You can read more about this in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.hashicorp.com&#x2F;nomad&#x2F;docs&#x2F;job-specification&#x2F;service#check&quot;&gt;Nomad documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Accessible by applications outside Nomad. In case &lt;code&gt;consul&lt;&#x2F;code&gt; is used by other applications outside of the Nomad cluster, they can still get their address (using DNS or REST APIs)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;However, Nomad native service discovery is perfect for local setups and even smaller use-cases in production because it eliminates the need of running Consul in your stack which is a big thing!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scenario-4-restricting-access-to-certain-namespaces&quot;&gt;Scenario 4: Restricting access to certain namespaces&lt;a class=&quot;zola-anchor&quot; href=&quot;#scenario-4-restricting-access-to-certain-namespaces&quot; aria-label=&quot;Anchor link for: scenario-4-restricting-access-to-certain-namespaces&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad_networking_consul_connect.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In all the above scenarios, we found that the service gets exposed to the local Nomad client. In case you’re running multiple namespaces on your cluster, you’d like to not expose them at all. In addition, you may want to express fine-grained controls on which application can access a particular service. All of this is possible via a &lt;strong&gt;Service Mesh&lt;&#x2F;strong&gt;. Nomad provides a way to have a “service mesh” via Consul Connect. Consul Connect can do mTLS and service authorization. Under the hood, it’s an Envoy proxy that runs alongside your app (sidecar is a fancy way to say that). The &lt;code&gt;consul&lt;&#x2F;code&gt; agent configures an Envoy configuration for you so it’s all pretty seamless.&lt;&#x2F;p&gt;
&lt;p&gt;For this to work, the first thing we need is a &lt;code&gt;bridge&lt;&#x2F;code&gt; network mode. This network model is actually a CNI plugin and needs to be installed separately in &lt;code&gt;&#x2F;opt&#x2F;cni&#x2F;bin&lt;&#x2F;code&gt;. Follow the steps mentioned &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;integrations&#x2F;consul-connect&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bridge&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;redis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The service in &lt;code&gt;redis&lt;&#x2F;code&gt; is called as a &lt;em&gt;Consul Connect Ingress&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      provider&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;consul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      connect&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        sidecar_service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It’s an empty block because we don’t need to define any upstream here. The rest of the values will be default values.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we create a service for our &lt;code&gt;app&lt;&#x2F;code&gt; and that is a &lt;em&gt;Consul Connect Egress&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      provider&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;consul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;      connect&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;        sidecar_service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;          proxy&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;            upstreams&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              destination_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              local_bind_port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6379&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here  we define an upstream for &lt;code&gt;redis&lt;&#x2F;code&gt;. If you notice closely, we are using a port number in &lt;em&gt;Consul Connect Ingress&lt;&#x2F;em&gt;. For some reason, if you use a named port instead of 6379 it doesn’t work. I am not entirely sure if it’s a bug or it’s intended to work like this.&lt;&#x2F;p&gt;
&lt;p&gt;So here, when the &lt;code&gt;app&lt;&#x2F;code&gt; wants to talk to redis, it talks to &lt;code&gt;localhost:6379&lt;&#x2F;code&gt; which is the local port that the Envoy sidecar is listening to. We can verify that using &lt;code&gt;netstat&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; netstat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;tulpvn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Active&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Internet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; connections&lt;&#x2F;span&gt;&lt;span&gt; (only&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; servers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Proto&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Recv-Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Send-Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;           Foreign&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         State&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       PID&#x2F;Program&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 127.0.0.2:19001&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         0.0.0.0:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               LISTEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span&gt;                   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0.0.0.0:23237&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;           0.0.0.0:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               LISTEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span&gt;                   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 127.0.0.1:6379&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          0.0.0.0:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               LISTEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span&gt;                   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcp6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;       0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :::8080&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                 :::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                    LISTEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      1&#x2F;.&#x2F;hello.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The traffic is sent from this port to the other Envoy proxy on a port that it advertises (and Consul automagically configured). That Envoy proxy further sends the traffic to the &lt;code&gt;redis&lt;&#x2F;code&gt; container on port 6379. The proxied traffic is securley encrypted via mTLS and authorized (via Consul Intentions - not covered in this post).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scenario-5-exposing-services-to-end-user&quot;&gt;Scenario 5: Exposing services to end-user&lt;a class=&quot;zola-anchor&quot; href=&quot;#scenario-5-exposing-services-to-end-user&quot; aria-label=&quot;Anchor link for: scenario-5-exposing-services-to-end-user&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad_networking_user_facing.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In the first scenario, we discussed using static ports. Well, it turns out it’s super helpful if you want to define a Traffic Ingress service. Unlike K8s, Nomad doesn’t have any Ingress Controllers, so the best way is to deploy these web proxies on each node as a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;schedulers#system&quot;&gt;system job&lt;&#x2F;a&gt; (which means it’s ensured to run on every client node) and bind them to a static port (say 443&#x2F;80). Then, configure your Load Balancers and register all the Nomad nodes as target IPs and their ports would be the static port you define. These Ingress proxies (like HAProxy&#x2F;Nginx) can then be used to talk to your application via any of the patterns we’ve mentioned above.&lt;&#x2F;p&gt;
&lt;p&gt;Typically, you’d want to use a “Host-Based” routing pattern for your ingress proxy to make a routing decision.&lt;&#x2F;p&gt;
&lt;p&gt;For eg, in case you have an &lt;code&gt;a.example.org&lt;&#x2F;code&gt; DNS record pointing to an ALB. Now, when the request comes to the ALB, it forwards to any one of the NGINX&#x2F;HAProxy. For HAProxy to correctly route the traffic to `a service, you can use a “Host” header.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;These were some of the common networking patterns that I’m aware of. Since some of these concepts are not really straightforward I hope the explanation helped in bringing some clarity.&lt;&#x2F;p&gt;
&lt;p&gt;There’s much more to this topic like Consul Gateways and multiple kind of CNIs which tweak how networking happens in the cluster but those are some really advanced topics that are out of the scope for this post.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How I expose services while self hosting</title>
        <published>2022-02-10T00:00:00+00:00</published>
        <updated>2022-02-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/exposing-services/"/>
        <id>https://mrkaran.dev/posts/exposing-services/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/exposing-services/">&lt;p&gt;I’ve often been asked how to expose public and private services running on DigitalOcean droplets&#x2F;RPis when self hosting apps. Most people don’t have access to a static IP for their RPis. I felt I’d summarize my approach to this in this blog post and hope it’ll be useful for others trying to do the same.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tools-i-use&quot;&gt;Tools I use&lt;a class=&quot;zola-anchor&quot; href=&quot;#tools-i-use&quot; aria-label=&quot;Anchor link for: tools-i-use&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;&quot;&gt;Tailscale&lt;&#x2F;a&gt;: I love this and I’ve &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;home-server-updates&#x2F;&quot;&gt;written about it in the past&lt;&#x2F;a&gt;. I am one of the early adopters, using this for 2 years now and while it can be replaced with other similar Wireguard based mesh services that have popped up recently, I still like the UX of this application a lot. In simpler words, &lt;em&gt;it just works!&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt;: I use Caddy as a webserver to host some static websites and as a reverse proxy for all the applications I’ve deployed. It makes the SSL setup a breeze, the config is nice to read as well. There’s nothing about Caddy to not like it if you’re not in the business of dealing with super high concurrent traffic on your website (in which case NGINX&#x2F;HAProxy&#x2F;Envoy et al might be worth looking at). I’ve never used Traefik myself, and while I know it makes the routing simple with Docker labels, I think my current approach with Caddy is also similar and easier for me to use without having to learn a new config.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.docker.com&#x2F;&quot;&gt;Docker&lt;&#x2F;a&gt;: All the services are containerized and I make special use of Docker networks, which I’ll show in the post.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup-overview&quot;&gt;Setup Overview&lt;a class=&quot;zola-anchor&quot; href=&quot;#setup-overview&quot; aria-label=&quot;Anchor link for: setup-overview&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;selfhosted-networking-setup.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I use 2 instances of Caddy for my setup:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Public: This is to reverse proxy all the public-facing websites.&lt;&#x2F;li&gt;
&lt;li&gt;Private: This is to reverse proxy all the internal websites.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;code&gt;docker-compose&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3.7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;addy_public&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;lt;do_floating_ip&amp;gt;:80:80&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;lt;do_floating_ip&amp;gt;:443:443&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ublic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;addy_internal&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;100.111.91.100:80:80&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;100.111.91.100:443:443&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nternal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ublic&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;addy_public&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nternal&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;addy_internal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is where most of the magic lies. I use 2 Docker networks &lt;code&gt;caddy_public&lt;&#x2F;code&gt; and &lt;code&gt;caddy_internal&lt;&#x2F;code&gt;. Both these networks are configured as Bridge Networks. The containers connected to the same bridge network can even reach other containers using internal DNS.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;em&gt;published&lt;&#x2F;em&gt; port section is the one of importance here.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;code&gt;internal&lt;&#x2F;code&gt; caddy instance, the TCP port 80 in the container is mapped to port 80 on the Docker host for connections to host IP &lt;code&gt;100.111.91.100&lt;&#x2F;code&gt; (this is a private IP and belongs to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;kb&#x2F;1015&#x2F;100.x-addresses&#x2F;&quot;&gt;CGNAT space&lt;&#x2F;a&gt;). The same is done for &lt;code&gt;caddy_public&lt;&#x2F;code&gt; where instead of Tailscale IP, the Floating IP of the DigitalOcean droplet is used.&lt;&#x2F;p&gt;
&lt;p&gt;Next comes the part where we’ll attach these networks to our applications. &lt;code&gt;docker-compose&lt;&#x2F;code&gt; by default creates a user-defined bridge network if you leave &lt;code&gt;networks&lt;&#x2F;code&gt; unspecified. However, if you want more granular control, you can specify the networks in the Compose spec itself.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s an example of &lt;code&gt;Plausible&lt;&#x2F;code&gt; compose spec which is exposed publicly:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lausible_events_db&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;andex&#x2F;clickhouse-server:21.3.2.5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lausible&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lausible&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lausible&#x2F;analytics:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lausible&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;eb&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;addy_public&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;xternal&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lausible&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lausible&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here you can see that the ClickHouse container is only attached to the &lt;code&gt;plausible&lt;&#x2F;code&gt; network. This &lt;code&gt;plausible&lt;&#x2F;code&gt; network is scoped only to these services defined in this file.&lt;&#x2F;p&gt;
&lt;p&gt;We can &lt;code&gt;exec&lt;&#x2F;code&gt; inside the &lt;code&gt;caddy_public&lt;&#x2F;code&gt; container and find out the IP of &lt;code&gt;plausible&lt;&#x2F;code&gt; and verify if the network is correctly configured and reachable:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; plausible&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;plausible&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; has&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 172.20.0.3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; plausible:8000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;html&amp;gt;&amp;lt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;You are being &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span&gt; href&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;login&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some notes on this setup:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You’ll also note that I haven’t &lt;em&gt;published&lt;&#x2F;em&gt; the port 8000 anywhere. Publishing is only required if you want to forward the traffic from your host network to the docker network (via the bridge). But here, since both are attached to the same network (&lt;code&gt;caddy_public&lt;&#x2F;code&gt;), that is not required anymore.&lt;&#x2F;li&gt;
&lt;li&gt;This also means that the only way someone can reach port 8000 on Plausible is only via the Caddy container (which is firewall restricted to Cloudflare IPs.)&lt;&#x2F;li&gt;
&lt;li&gt;The DB container doesn’t need to be accessed at all from Caddy, so we’ve not attached the &lt;code&gt;web&lt;&#x2F;code&gt; network there&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here’s another example of exposing an internal service, which works on the same principles:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rafana&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rafana&#x2F;grafana:8.3.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;onitoring&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nternal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nternal&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;addy_internal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;xternal&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;onitoring&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;onitoring&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, the Grafana container is attached to &lt;code&gt;caddy_internal&lt;&#x2F;code&gt; network. Since the &lt;code&gt;caddy_internal&lt;&#x2F;code&gt; container only publishes ports on the Tailscale IP, anyone who is not inside the Tailscale network will not be able to access this. Tailscale can do much more by setting up ACL rules per device for each user, but since I am the only user, I’ve not configured ACL rules on it yet.&lt;&#x2F;p&gt;
&lt;p&gt;Hope this approach was simplistic enough. I follow this pattern across all the applications I self-host and honestly pretty happy with it&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using ClickHouse Keeper for Replication</title>
        <published>2021-12-17T08:10:55+05:30</published>
        <updated>2021-12-17T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/clickhouse-replication/"/>
        <id>https://mrkaran.dev/posts/clickhouse-replication/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/clickhouse-replication/">&lt;p&gt;ClickHouse is an extremely performant columnar DB used for fast analytical processing. ClickHouse supports data &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;docs&#x2F;en&#x2F;engines&#x2F;table-engines&#x2F;mergetree-family&#x2F;replication&#x2F;&quot;&gt;replication&lt;&#x2F;a&gt; using Apache Zookeeper which needs to be deployed externally. While Zookeeper works well after you’ve tuned it properly, it was still an additional maintenance overhead. The good news is that you don’t have to worry about this anymore.&lt;&#x2F;p&gt;
&lt;p&gt;ClickHouse 21.12 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;blog&#x2F;en&#x2F;2021&#x2F;clickhouse-v21.12-released&#x2F;&quot;&gt;release annoucement&lt;&#x2F;a&gt; mentions &lt;code&gt;ClickHouse Keeper&lt;&#x2F;code&gt; as feature complete. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;docs&#x2F;en&#x2F;operations&#x2F;clickhouse-keeper&#x2F;&quot;&gt;Keeper&lt;&#x2F;a&gt; is a replacement for Zookeeper, written in C++ and uses the RAFT algorithm for consensus across different nodes in the cluster. It also has some nice improvements over Zookeeper, such as compressed snapshots&#x2F;logs of the state changes in the cluster and the ability to run it &lt;em&gt;inside&lt;&#x2F;em&gt; the server binary itself. I decided to spin up a local Clickhouse cluster and test out the new &lt;code&gt;clickhouse-keeper&lt;&#x2F;code&gt; feature.&lt;&#x2F;p&gt;
&lt;p&gt;For our local setup, we’ll set up &lt;strong&gt;4 nodes&lt;&#x2F;strong&gt;. We’ll create &lt;strong&gt;2 shards&lt;&#x2F;strong&gt; to distribute our data and each shard will have &lt;strong&gt;2 replicas each&lt;&#x2F;strong&gt;. The setup looks something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clickhouse-cluster.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We need to run &lt;code&gt;clickhouse-keeper&lt;&#x2F;code&gt; only on 3 of these nodes to ensure a quorum. Here’s a sample &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; to spin up these nodes as containers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3.7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;-clickhouse-defaults&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;clickhouse-defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;estart&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nless-stopped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;andex&#x2F;clickhouse-server:21.12.2.17&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;proc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 65535&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ofile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;oft&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 262144&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ard&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 262144&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lickhouse-blue-1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ontainer_name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-blue-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ostname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-blue-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;000:9000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;123:8123&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;181:9181&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olume&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h-blue-1-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;var&#x2F;lib&#x2F;clickhouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&#x2F;configs&#x2F;gen&#x2F;clickhouse-blue-1:&#x2F;etc&#x2F;clickhouse-server&#x2F;config.d&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lickhouse-blue-2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ontainer_name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-blue-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ostname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-blue-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;001:9000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;124:8123&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;182:9181&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olume&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h-blue-2-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;var&#x2F;lib&#x2F;clickhouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&#x2F;configs&#x2F;gen&#x2F;clickhouse-blue-2:&#x2F;etc&#x2F;clickhouse-server&#x2F;config.d&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lickhouse-green-1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ontainer_name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-green-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ostname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-green-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;002:9000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;125:8123&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;183:9181&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olume&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h-green-1-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;var&#x2F;lib&#x2F;clickhouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&#x2F;configs&#x2F;gen&#x2F;clickhouse-green-1:&#x2F;etc&#x2F;clickhouse-server&#x2F;config.d&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lickhouse-green-2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ontainer_name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-green-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ostname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-green-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;003:9000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;126:8123&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;184:9181&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olume&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h-green-2-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;var&#x2F;lib&#x2F;clickhouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&#x2F;configs&#x2F;gen&#x2F;clickhouse-green-2:&#x2F;etc&#x2F;clickhouse-server&#x2F;config.d&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;h-blue-1-data&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;h-blue-2-data&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;h-green-1-data&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;h-green-2-data&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;clickhouse-keeper&lt;&#x2F;code&gt; runs only if the &lt;code&gt;&amp;lt;keeper_config&amp;gt;&lt;&#x2F;code&gt; section is present inside the config. Here’s a sample config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;clickhouse&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;keeper_server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tcp_port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;9181&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tcp_port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server_id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;${SERVER_ID}&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server_id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;log_storage_path&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;var&#x2F;lib&#x2F;clickhouse&#x2F;coordination&#x2F;log&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;log_storage_path&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;snapshot_storage_path&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;var&#x2F;lib&#x2F;clickhouse&#x2F;coordination&#x2F;snapshots&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;snapshot_storage_path&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;coordination_settings&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;operation_timeout_ms&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;10000&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;operation_timeout_ms&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;session_timeout_ms&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;30000&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;session_timeout_ms&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;raft_logs_level&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;raft_logs_level&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;coordination_settings&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;raft_configuration&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-blue-1&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;9234&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-blue-2&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;9234&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;3&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-green-1&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;9234&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;raft_configuration&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;keeper_server&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;clickhouse&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are some other configs required for Clickhouse to discover other nodes and enable replication. You can find a working example in this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;clickhouse-keeper-example&quot;&gt;repo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verifying-cluster-state&quot;&gt;Verifying Cluster State&lt;a class=&quot;zola-anchor&quot; href=&quot;#verifying-cluster-state&quot; aria-label=&quot;Anchor link for: verifying-cluster-state&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Once the containers are configured and running, we can verify if the replication is working as intended:&lt;&#x2F;p&gt;
&lt;p&gt;Let’s first check if the &lt;code&gt;keeper&lt;&#x2F;code&gt; daemon is running by:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ruok&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; nc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9181&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;imok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;ruok&lt;&#x2F;code&gt; is a part of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;docs&#x2F;en&#x2F;operations&#x2F;clickhouse-keeper&#x2F;#four-letter-word-commands&quot;&gt;Four Letter Commands&lt;&#x2F;a&gt; that are mostly used to diagnose Keeper’s client&#x2F;server.&lt;&#x2F;p&gt;
&lt;p&gt;To ensure that &lt;code&gt;clickhouse-server&lt;&#x2F;code&gt; is aware of the &lt;code&gt;keeper&lt;&#x2F;code&gt; cluster, we can query the &lt;code&gt;system.zookeeper&lt;&#x2F;code&gt; table:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; system&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;zookeeper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FORMAT Vertical&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Query id: 287d3c2d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;b93f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4d48&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;b335&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;6df2f89a8ab3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;──────&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;:           clickhouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;:          &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;czxid:          &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mzxid:          &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ctime:          &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;05&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mtime:          &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;05&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;version&lt;&#x2F;span&gt;&lt;span&gt;:        &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cversion:       &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;aversion:       &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ephemeralOwner: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dataLength:     &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;numChildren:    &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pzxid:          &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;:           &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you don’t see any results in the &lt;code&gt;system.zookeeper&lt;&#x2F;code&gt; table, then re-check if &lt;code&gt;zookeeper&lt;&#x2F;code&gt; section is present inside the config. This config tells ClickHouse how to discover keeper nodes.&lt;&#x2F;p&gt;
&lt;p&gt;We can also see if our cluster is configured correctly with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    host_name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    host_address,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    replica_num&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; system&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;clusters&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; cluster &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Query id: a4bacfa1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;d3aa&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;482f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;b8b2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;30b05442a173&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─host_name──────────┬─host_address─┬─replica_num─┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;blue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;  │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;172&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;19&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;   │           &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;blue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;  │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;172&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;19&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;   │           &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;172&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;19&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;   │           &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;172&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;19&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;   │           &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴──────────────┴─────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Here &lt;code&gt;events&lt;&#x2F;code&gt; is our cluster name specified in the &lt;code&gt;remote_servers&lt;&#x2F;code&gt; section of the config.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inserting-sample-data&quot;&gt;Inserting Sample Data&lt;a class=&quot;zola-anchor&quot; href=&quot;#inserting-sample-data&quot; aria-label=&quot;Anchor link for: inserting-sample-data&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s create a DB and add some data to the DB. We need to ensure that our data is split across shards and we can query all shards using a central &lt;em&gt;view&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cluster-schema&quot;&gt;Cluster Schema&lt;a class=&quot;zola-anchor&quot; href=&quot;#cluster-schema&quot; aria-label=&quot;Anchor link for: cluster-schema&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DATABASE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ON&lt;&#x2F;span&gt;&lt;span&gt; CLUSTER &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.events_local &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; CLUSTER &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{cluster}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    event_id  Int32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    uuid UUID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENGINE &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ReplicatedMergeTree(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;clickhouse&#x2F;tables&#x2F;{cluster}&#x2F;{shard}&#x2F;{table}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{replica}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;PARTITION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; BY&lt;&#x2F;span&gt;&lt;span&gt; toYYYYMM(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; (event_id);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.events_main &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; CLUSTER &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{cluster}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENGINE &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; Distributed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{cluster}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, app, events_local, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;rand&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What’s happening here:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We’ll create a sample database &lt;code&gt;app&lt;&#x2F;code&gt; with a single table &lt;code&gt;events_local&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We’re using &lt;code&gt;ReplicatedMergeTree&lt;&#x2F;code&gt; here as that tells &lt;code&gt;ClickHouse&lt;&#x2F;code&gt; to automatically replicate the data inside the table when it’s inserted.
&lt;ul&gt;
&lt;li&gt;Properties like &lt;code&gt;cluster&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;shard&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;replica&lt;&#x2F;code&gt; are automatically populated from the server’s &lt;em&gt;macros&lt;&#x2F;em&gt;. It’s a handy feature that allows you to execute this command just &lt;em&gt;once&lt;&#x2F;em&gt; on the cluster and it automatically populates the relevant config in each server.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Finally we create a  &lt;code&gt;Distributed&lt;&#x2F;code&gt; table to perform our &lt;code&gt;INSERT&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;SELECT&lt;&#x2F;code&gt; operations in a central place. It’s possible to manually insert data to particular replicas, but since Clickhouse supports load balancing across shards, it’s preferred to create a table with a &lt;code&gt;Distributed&lt;&#x2F;code&gt; engine and let that happen automatically.
&lt;ul&gt;
&lt;li&gt;Write operations can be sharded based on a particular column name, but here we are simply using the &lt;code&gt;rand()&lt;&#x2F;code&gt; function, which splits the write randomly to different shards.&lt;&#x2F;li&gt;
&lt;li&gt;All read operations are parallelized and Clickhouse selects one replica from each shard to query the data from.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;We use &lt;code&gt;ON CLUSTER&lt;&#x2F;code&gt; keyword to indicate that this query has to be run on all servers which are part of the cluster &lt;code&gt;events&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It’s now time to insert some random data, for which you can use this command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;rand&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;), generateUUIDv4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now query the table and see if our records are present:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1888949839&lt;&#x2F;span&gt;&lt;span&gt; │ 3c33305e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8ea0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4ac1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;a07a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;667465ec9a85 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;689113926&lt;&#x2F;span&gt;&lt;span&gt; │ 2a944d71&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;73f3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4491&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;b851&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4f0e6f296e44 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬──event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;415899002&lt;&#x2F;span&gt;&lt;span&gt; │ 5980299f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1594&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4c17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8eb5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;e512f15ecf34 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────────────────┴───────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1303963476&lt;&#x2F;span&gt;&lt;span&gt; │ 0b27d5bd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;6315&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4937&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;82a4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;18199e5eebb7 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, you must be wondering how to check if the data is replicated and how the data is distributed across our shards. For that, we can use the handy &lt;code&gt;remote()&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;172.20.0.2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    UNION ALL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;172.20.0.3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    UNION ALL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;172.20.0.4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    UNION ALL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;172.20.0.5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Query id: 34a81447&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;a31b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4915&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;9bd8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;7a6e17bb0860&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;blue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1888949839&lt;&#x2F;span&gt;&lt;span&gt; │ 3c33305e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8ea0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4ac1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;a07a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;667465ec9a85 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└───────────────────┴─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;blue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1888949839&lt;&#x2F;span&gt;&lt;span&gt; │ 3c33305e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8ea0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4ac1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;a07a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;667465ec9a85 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└───────────────────┴─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;─────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬──event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;415899002&lt;&#x2F;span&gt;&lt;span&gt; │ 5980299f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1594&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4c17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8eb5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;e512f15ecf34 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴─────────────────────┴───────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;─────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;689113926&lt;&#x2F;span&gt;&lt;span&gt; │ 2a944d71&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;73f3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4491&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;b851&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4f0e6f296e44 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;─────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1303963476&lt;&#x2F;span&gt;&lt;span&gt; │ 0b27d5bd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;6315&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4937&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;82a4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;18199e5eebb7 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;─────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1303963476&lt;&#x2F;span&gt;&lt;span&gt; │ 0b27d5bd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;6315&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4937&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;82a4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;18199e5eebb7 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;─────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬──event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;415899002&lt;&#x2F;span&gt;&lt;span&gt; │ 5980299f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1594&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4c17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8eb5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;e512f15ecf34 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴─────────────────────┴───────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;─────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬───event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;36&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;689113926&lt;&#x2F;span&gt;&lt;span&gt; │ 2a944d71&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;73f3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4491&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;b851&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4f0e6f296e44 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴─────────────────────┴────────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! We can see our data is sharded as some parts of it exists in &lt;code&gt;green&lt;&#x2F;code&gt; and &lt;code&gt;blue&lt;&#x2F;code&gt;. We can also see that for each record, we have 2 entries thus confirming that &lt;code&gt;ReplicatedMergeTree&lt;&#x2F;code&gt; is doing its job!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;additional-scenarios&quot;&gt;Additional Scenarios&lt;a class=&quot;zola-anchor&quot; href=&quot;#additional-scenarios&quot; aria-label=&quot;Anchor link for: additional-scenarios&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;All is well and good so far, but to ensure that our cluster setup is resilient we need to introduce our cluster to some &lt;em&gt;Non-Happy&lt;&#x2F;em&gt; scenarios.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stop-a-replica-node&quot;&gt;Stop a replica node&lt;a class=&quot;zola-anchor&quot; href=&quot;#stop-a-replica-node&quot; aria-label=&quot;Anchor link for: stop-a-replica-node&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clickhouse-cluster-replica-down.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker-compose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stop&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-green-2&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stopping&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-green-2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, let’s query our records:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)─┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│       &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt; │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That seems right. We’re able to access all our data with just one replica down.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s try inserting data and bring back the replica to see if it got automatically replicated or not:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;rand&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;), generateUUIDv4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Ok.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬──event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;375826335&lt;&#x2F;span&gt;&lt;span&gt; │ 8dbbc9cf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8f00&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4cc3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;a4fb&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;0f17a68340e5 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────────────────┴───────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s start the replica again:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker-compose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-green-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Starting&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-green-2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On querying the replica to see if it has the data:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;172.20.0.5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Query id: 422041dc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;afe8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4f28&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;9659&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;6d58726f8c90&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;─────────┬────────────────&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;─┬──event_id─┬─uuid─────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;09&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;375826335&lt;&#x2F;span&gt;&lt;span&gt; │ 8dbbc9cf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;8f00&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;4cc3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;a4fb&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;0f17a68340e5 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────────────────┴─────────────────────┴───────────┴──────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! The record &lt;code&gt;375826335&lt;&#x2F;code&gt; automatically got replicated once the replica was healthy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stop-a-keeper-node&quot;&gt;Stop a Keeper Node&lt;a class=&quot;zola-anchor&quot; href=&quot;#stop-a-keeper-node&quot; aria-label=&quot;Anchor link for: stop-a-keeper-node&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clickhouse-cluster-keeper-1-down.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We’ll stop a server instance that is running the &lt;code&gt;clickhouse-keeper&lt;&#x2F;code&gt; process. By doing this, we’ll also be killing a replica, but that is okay.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker-compose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stop&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-blue-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stopping&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-blue-2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s insert some data:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;rand&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;), generateUUIDv4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can check the server information of the other 2 &lt;code&gt;keeper&lt;&#x2F;code&gt; nodes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; nc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9181&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Mode:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; follower&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; nc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9183&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Mode:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; leader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, one of the &lt;code&gt;keeper&lt;&#x2F;code&gt; nodes has elected itself to be the leader and we have no problems in the setup so far. However, if we stop another &lt;code&gt;keeper&lt;&#x2F;code&gt; node, then there will be only &lt;code&gt;keeper&lt;&#x2F;code&gt; node remaining in the setup and to avoid a &lt;em&gt;Split Brain&lt;&#x2F;em&gt; issue, it won’t be able to elect itself as the leader.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clickhouse-cluster-keeper-2-down.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What happens then? Only one way to find out:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker-compose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stop&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-blue-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Stopping&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clickhouse-blue-1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;events_main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;rand&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;), generateUUIDv4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Received exception &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; server&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 21&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Code: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;242&lt;&#x2F;span&gt;&lt;span&gt;. DB::Exception: Received &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; localhost:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;9000&lt;&#x2F;span&gt;&lt;span&gt;. DB::Exception: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;Table&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; is&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; readonly&lt;&#x2F;span&gt;&lt;span&gt; mode (zookeeper &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;tables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;events&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;green&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;table&lt;&#x2F;span&gt;&lt;span&gt;). (TABLE_IS_READ_ONLY)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ah! So, we can still query for the data (which will be incomplete since &lt;em&gt;blue&lt;&#x2F;em&gt; shard is completely down), but we cannot insert any new data at all. We can even verify this by querying for the health of the &lt;code&gt;keeper&lt;&#x2F;code&gt; node:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mntr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; nc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; localhost&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9183&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;This&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; instance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; is&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; currently&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; serving&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; requests%&lt;&#x2F;span&gt;&lt;span&gt;                                                                                                                              &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;add-a-new-shard&quot;&gt;Add a new shard&lt;a class=&quot;zola-anchor&quot; href=&quot;#add-a-new-shard&quot; aria-label=&quot;Anchor link for: add-a-new-shard&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clickhouse-cluster-orange-shard.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Alright, so our tests so far have been quite good and show that the cluster is resilient to failures as long as there exists a &lt;code&gt;keeper&lt;&#x2F;code&gt; node running as &lt;code&gt;leader&lt;&#x2F;code&gt; mode in the quorum. Now, let’s see how to add a new shard. We’ll extend our &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; to add a new &lt;code&gt;orange&lt;&#x2F;code&gt; shard:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lickhouse-orange-1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ontainer_name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-orange-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ostname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lickhouse-orange-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;004:9000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;127:8123&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;185:9181&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olume&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h-orange-1-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;var&#x2F;lib&#x2F;clickhouse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&#x2F;configs&#x2F;gen&#x2F;clickhouse-orange-1:&#x2F;etc&#x2F;clickhouse-server&#x2F;config.d&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Inside our &lt;code&gt;remote_servers.xml&lt;&#x2F;code&gt;, we’ll add the &lt;code&gt;orange&lt;&#x2F;code&gt; shard as well:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;shard&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;internal_replication&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;internal_replication&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;replica&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;clickhouse-orange-1&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;9000&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;replica&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;shard&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s pretty much it. Let’s start the new replica:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker-compose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s insert some data and query if the shard is getting data or not:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    hostName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;172.20.0.2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Received exception &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; server&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 21&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Code: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;519&lt;&#x2F;span&gt;&lt;span&gt;. DB::Exception: Received &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; localhost:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;9000&lt;&#x2F;span&gt;&lt;span&gt;. DB::Exception: All attempts &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; table&lt;&#x2F;span&gt;&lt;span&gt; structure failed. &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;Log&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Code: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;279&lt;&#x2F;span&gt;&lt;span&gt;. DB::NetException: All &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;connection&lt;&#x2F;span&gt;&lt;span&gt; tries failed. &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;Log&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;There &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;is&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; no&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; table&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;events_local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; on&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; server&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;172&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;9000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;. (ALL_CONNECTION_TRIES_FAILED) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 21&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;17&lt;&#x2F;span&gt;&lt;span&gt; (official build))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;. (NO_REMOTE_SHARD_AVAILABLE)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Houston, we have a problem.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; There is no table `app`.`events_local` on server: 172.20.0.2:9000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is mentioned in the ClickHouse docs on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;docs&#x2F;en&#x2F;engines&#x2F;table-engines&#x2F;mergetree-family&#x2F;replication&#x2F;&quot;&gt;Replication&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;CREATE, DROP, ATTACH, DETACH and RENAME queries are executed on a single server and are not replicated:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This means that although we’d run &lt;code&gt;CREATE DATABASE&lt;&#x2F;code&gt; and &lt;code&gt;CREATE TABLE&lt;&#x2F;code&gt; commands using &lt;code&gt;ON CLUSTER&lt;&#x2F;code&gt; which executes on all servers, but since the &lt;code&gt;orange-1&lt;&#x2F;code&gt; node is introduced &lt;em&gt;after&lt;&#x2F;em&gt; we ran that command, we need to manually create the DB and Table here. We have to execute the below commands &lt;em&gt;inside&lt;&#x2F;em&gt; the &lt;code&gt;orange-1&lt;&#x2F;code&gt; replica:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DATABASE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; app&lt;&#x2F;span&gt;&lt;span&gt;.events_local (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    event_id  Int32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    uuid UUID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENGINE &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ReplicatedMergeTree(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;clickhouse&#x2F;tables&#x2F;{cluster}&#x2F;{shard}&#x2F;{table}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{replica}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;PARTITION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; BY&lt;&#x2F;span&gt;&lt;span&gt; toYYYYMM(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; (event_id);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s all that is required. Adding a new replica is also the same process.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Hope this tutorial helped you figure out how to use &lt;code&gt;clickhouse-keeper&lt;&#x2F;code&gt; to set up a distributed ClickHouse cluster DB. &lt;code&gt;clickhouse-keeper&lt;&#x2F;code&gt; is still a relatively new feature as the docs mention already, but given that it solves operations overhead of running a Zookeeper cluster, it’s worth checking it out.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;a class=&quot;zola-anchor&quot; href=&quot;#references&quot; aria-label=&quot;Anchor link for: references&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=abhcCRW09Ac&quot;&gt;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=abhcCRW09Ac&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;Slides used in above talk: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;presentations.clickhouse.com&#x2F;meetup54&#x2F;keeper.pdf&quot;&gt;https:&#x2F;&#x2F;presentations.clickhouse.com&#x2F;meetup54&#x2F;keeper.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.com&#x2F;docs&#x2F;en&#x2F;operations&#x2F;clickhouse-keeper&#x2F;&quot;&gt;https:&#x2F;&#x2F;clickhouse.com&#x2F;docs&#x2F;en&#x2F;operations&#x2F;clickhouse-keeper&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ClickHouse&#x2F;ClickHouse&#x2F;tree&#x2F;master&#x2F;tests&#x2F;integration&#x2F;test_keeper_multinode_simple&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;ClickHouse&#x2F;ClickHouse&#x2F;tree&#x2F;master&#x2F;tests&#x2F;integration&#x2F;test_keeper_multinode_simple&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ClickHouse&#x2F;ClickHouse&#x2F;issues&#x2F;2161&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;ClickHouse&#x2F;ClickHouse&#x2F;issues&#x2F;2161&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For the full code&#x2F;config samples, you can check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;clickhouse-keeper-example&quot;&gt;repo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;updates&quot;&gt;Updates&lt;a class=&quot;zola-anchor&quot; href=&quot;#updates&quot; aria-label=&quot;Anchor link for: updates&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;If you have setup RBAC on your cluster, make sure you add &lt;code&gt;&amp;lt;user&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;lt;password&amp;gt;&lt;&#x2F;code&gt; fields to the &lt;code&gt;&amp;lt;remote_server&amp;gt;&lt;&#x2F;code&gt; configuration.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Breaking Software and Getting Older</title>
        <published>2021-12-09T08:10:55+05:30</published>
        <updated>2021-12-09T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/breaking-software/"/>
        <id>https://mrkaran.dev/posts/breaking-software/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/breaking-software/">&lt;p&gt;Recently, I’d posted on Twitter that my feed has become &lt;em&gt;messy&lt;&#x2F;em&gt; overtime. Maybe I followed some accounts that were of no interest, maybe Twitter’s algos don’t really know what to show to me. Whatever, I wanted a fresh start. And, I’ve done this in past. I’ve removed all the accounts that I follow but they don’t follow me back. This little trick is helpful to start afresh while still not offending your friends ;)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;twitter_cleanup.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I’d written a really simple Python script to do the job! It looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; tweepy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;SCREEN_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;CONSUMER_KEY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;CONSUMER_SECRET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ACCESS_TOKEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ACCESS_TOKEN_SECRET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;auth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; tweepy&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;OAuthHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;CONSUMER_KEY&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; CONSUMER_SECRET&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;set_access_token&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ACCESS_TOKEN&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; ACCESS_TOKEN_SECRET&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; tweepy&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;API&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;followers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;followers_ids&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;SCREEN_NAME&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;friends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;friends_ids&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;SCREEN_NAME&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; friends&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; followers&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Unfollow &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{0}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get_user&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;f&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;screen_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;destroy_friendship&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;f&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I’d last ran this in 2019 or so. That is dinosaur ages in the world of software. All I wanted to do was run this goddamn script again, 2 years later. Seems to be too much of an ask? Apparently &lt;code&gt;tweepy&lt;&#x2F;code&gt; the library used here to interact with Twitter’s APIs had a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tweepy&#x2F;tweepy&#x2F;releases&#x2F;tag&#x2F;v4.0.0&quot;&gt;major release&lt;&#x2F;a&gt; with lots of breaking changes. They’ve internally migrated to start using v2 Twitter API. So, when I naively ran &lt;code&gt;pip install tweepy&lt;&#x2F;code&gt;, my code threw:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;❯ &lt;&#x2F;span&gt;&lt;span&gt;python&lt;&#x2F;span&gt;&lt;span&gt; main&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;py&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Traceback&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;most&lt;&#x2F;span&gt;&lt;span&gt; recent&lt;&#x2F;span&gt;&lt;span&gt; call&lt;&#x2F;span&gt;&lt;span&gt; last&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  File&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;home&#x2F;karan&#x2F;Code&#x2F;Personal&#x2F;twitter-unfollow&#x2F;main.py&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 13&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    followers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;followers_ids&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;SCREEN_NAME&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;AttributeError&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;API&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; object&lt;&#x2F;span&gt;&lt;span&gt; has&lt;&#x2F;span&gt;&lt;span&gt; no&lt;&#x2F;span&gt;&lt;span&gt; attribute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;followers_ids&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, some method name changed. But that’s not all. The whole auth process including the initialisation of the API object changed as well. I’d spent some ~15 minutes grokking the docs but frustrated because 1) I don’t give a shit about v2&#x2F;v1 APIs. 2) I just want to &lt;em&gt;carry&lt;&#x2F;em&gt; on with whatever I was doing. Why is this shit taking more time than I can care to give this to?&lt;&#x2F;p&gt;
&lt;p&gt;I’d have cared enough if it was a side-project I maintained or something that I used daily. A utility like this which gets used once in a couple of years, &lt;strong&gt;will&lt;&#x2F;strong&gt; see more such breaking changes in future. Why, then should I spend migrating to v2 APIs, when after 2 years, v3 APIs would have broken my code again? What is the damn point? Why can’t software just keep working without troubling their users?&lt;&#x2F;p&gt;
&lt;p&gt;In the end, I just installed the last version that works with &lt;code&gt;v1&lt;&#x2F;code&gt; APIs and ran the script.&lt;&#x2F;p&gt;
&lt;p&gt;I get breaking changes, I totally do. And I’ve no qualms with Tweepy. They did what they had to, in order to be compatible with v2. I am just angry&#x2F;sad at the whole ecosystem of “Move fast, break things”.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Please. Slow. Down.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So that the rest of us who have a life can enjoy it and not spend an entire weekend migrating across versions!&lt;&#x2F;p&gt;
&lt;p&gt;Sigh&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Debugging issues with Packer and Ansible in Docker</title>
        <published>2021-11-16T00:00:00+05:30</published>
        <updated>2021-11-16T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/debugging-packer-ci/"/>
        <id>https://mrkaran.dev/posts/debugging-packer-ci/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/debugging-packer-ci/">&lt;p&gt;Today I faced an issue that questioned my sanity. Since I didn’t find many “related” issues on StackOverflow&#x2F;Google-fu except a lone GitHub thread where a kind stranger hinted at what could be the issue, I am writing about it here in the hopes (although I don’t wish this torture on anyone) that it helps someone!&lt;&#x2F;p&gt;
&lt;p&gt;To give some context, I am running a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;ci&#x2F;&quot;&gt;Gitlab CI&lt;&#x2F;a&gt; job that bakes an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AWSEC2&#x2F;latest&#x2F;UserGuide&#x2F;AMIs.html&quot;&gt;AMI&lt;&#x2F;a&gt; using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.packer.io&#x2F;&quot;&gt;Packer&lt;&#x2F;a&gt;. Packer can use different kinds of provisioners to do configure stuff on the host and then prepare the image. I am using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.packer.io&#x2F;docs&#x2F;provisioners&#x2F;ansible&#x2F;ansible&quot;&gt;Ansible provisioner&lt;&#x2F;a&gt; to install and configure &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.consul.io&#x2F;&quot;&gt;Consul&lt;&#x2F;a&gt;. At this point you may think this post is sponsored by Hashicorp by the sheer mention of all their products, but I assure you that is not the case.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, so this role works locally but it fails on the damn Gitlab CI. Classic case of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;memegenerator.net&#x2F;instance&#x2F;64569365&#x2F;disaster-girl-worked-fine-on-local-dev-ops-problem-now&quot;&gt;Works on my machine, Ops problem now&lt;&#x2F;a&gt;. These kinds of issues although are particularly exciting for me because they give me a chance to dig down deeper in the internals and slowly peel apart layers to figure out where the “drift” between local and CI is happening.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the relevant Packer snippet (Oh and this week as I updated myself with new Packer releases, it’s now possible to write Packer config with HCL and not just JSON anymore! Yayie. Again a reminder: not a sponsored post).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  sources&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;source.amazon-ebs.golden-ami&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  provisioner&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;ansible&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    playbook_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;           =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;playbook_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    extra_arguments&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;         =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;--tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ansible_python_interpreter=&#x2F;usr&#x2F;bin&#x2F;python3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ansible_env_vars&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ANSIBLE_LOCAL_TEMP=$HOME&#x2F;.ansible&#x2F;tmp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ANSIBLE_REMOTE_TEMP=$HOME&#x2F;.ansible&#x2F;tmp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    galaxy_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;             =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;galaxy_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inventory_file_template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[consul_instances]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ .HostAlias }} ansible_host={{ .Host }} ansible_user={{ .User }} ansible_port={{ .Port }}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running &lt;code&gt;packer build&lt;&#x2F;code&gt; in CI results in a failure of a task defined in the Ansible playbook. The task simply creates a new group:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dd Consul group&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;roup&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ consul_group }}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tate&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;resent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hen&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;onsul_manage_group | bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.ansible.com&#x2F;ansible&#x2F;latest&#x2F;collections&#x2F;ansible&#x2F;builtin&#x2F;group_module.html&quot;&gt;&lt;code&gt;group&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; runs &lt;code&gt;groupapp&lt;&#x2F;code&gt; command behind the scenes and you should be in the list of sudoers to actually create new groups. Since I already have &lt;code&gt;become: true&lt;&#x2F;code&gt; and &lt;code&gt;become_user: root&lt;&#x2F;code&gt; in my playbook that requirement is fulfilled. Moreover, this task runs just fine in the local as I mentioned above. While running in CI, I see the following error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;amazon-ebs.golden-ami: TASK [consul : Add Consul group] ***********************************************&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;amazon-ebs.golden-ami: fatal: [default]: FAILED! =&amp;gt; {&amp;quot;changed&amp;quot;: false, &amp;quot;msg&amp;quot;: &amp;quot;groupadd: Permission denied.\ngroupadd: cannot lock &#x2F;etc&#x2F;group; try again later.\n&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;consul&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Erhm, okayyy. That looks like a permission error. But why does this not happen in my local was the question eating me up.&lt;&#x2F;p&gt;
&lt;p&gt;Now was the time to start from the ground up and dissect different things going here. I will add a small hint though: The Gitlab CI runner is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;runner&#x2F;executors&#x2F;docker.html&quot;&gt;Docker-based&lt;&#x2F;a&gt; runner. That means all the commands like &lt;code&gt;packer build&lt;&#x2F;code&gt; etc happen inside a Docker container. I am using &lt;code&gt;hashicorp&#x2F;packer:light&lt;&#x2F;code&gt; image, which is an Alpine based image containing just the &lt;code&gt;packer&lt;&#x2F;code&gt; executable.&lt;&#x2F;p&gt;
&lt;p&gt;I tried to run the container locally with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;pwd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;:&#x2F;app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;it&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-entrypoint=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hashicorp&#x2F;packer:light&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And yes. When I ran &lt;code&gt;packer build&lt;&#x2F;code&gt;, I could replicate the issue here! But wait. More questions than answers. Ansible would run this &lt;code&gt;groupadd&lt;&#x2F;code&gt; command on the remote host, right? Why does Ansible care if it’s inside a container or not? So, I created a really simple playbook to reproduce this further.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- name: Assemble Consul cluster&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hosts: localhost&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  any_errors_fatal: true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  become: true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  become_user: root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  tasks:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - name: Add Consul group&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      group:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name: debug_consul&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        state: present&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I ran this &lt;code&gt;ansible-playbook test.yml&lt;&#x2F;code&gt; inside the container and… it worked! Okay, now it’s becoming clear. We aren’t executing &lt;code&gt;ansible-playbook&lt;&#x2F;code&gt; directly, it’s being wrapped by Packer. So this is clearly getting messed up by Packer. This time I did find a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;packer&#x2F;issues&#x2F;5421&quot;&gt;GitHub issue&lt;&#x2F;a&gt; where people were asking about similar issues and this person described it well:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;packer_root_issue.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I opened &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.packer.io&#x2F;docs&#x2F;provisioners&#x2F;ansible&#x2F;ansible#become-yes&quot;&gt;Packer docs&lt;&#x2F;a&gt; again and that’s when I read this:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;We recommend against running Packer as root; if you do then you won’t be able to successfully run your Ansible playbook as root; become: yes will fail.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;WTF!!! This was right there in the docs, hiding in plain sight. Sheesh!&lt;&#x2F;p&gt;
&lt;p&gt;Okay, so I can not run my playbook with &lt;code&gt;become: true&lt;&#x2F;code&gt; with the packer Image (which uses root user). Time to fix that by building a custom image. That is because Gitlab CI &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-runner&#x2F;-&#x2F;issues&#x2F;2750&quot;&gt;won’t let me change the user&lt;&#x2F;a&gt; without hacking stuff. And a custom image also allows me to ditch Alpine for Ubuntu, which is what I prefer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FROM ubuntu:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    python3 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    git \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    unzip \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    python3-pip \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;amp;&amp;amp; rm -rf &#x2F;var&#x2F;lib&#x2F;apt&#x2F;lists&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;RUN curl -o packer.zip https:&#x2F;&#x2F;releases.hashicorp.com&#x2F;packer&#x2F;1.7.8&#x2F;packer_1.7.8_linux_amd64.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;RUN unzip packer.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;RUN mv packer &#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;RUN pip3 install ansible&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;RUN useradd -rm -d &#x2F;home&#x2F;ubuntu -s &#x2F;bin&#x2F;bash -g root -G sudo -u 1000 ubuntu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;USER ubuntu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WORKDIR &#x2F;tmp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENV PATH=&amp;quot;$HOME&#x2F;.local&#x2F;bin:$PATH&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WORKDIR &#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using this custom image, the packer build worked just fine. Fun day indeed (&#x2F;s).&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Load testing with K6</title>
        <published>2021-10-29T00:00:00+05:30</published>
        <updated>2021-10-29T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/load-testing-k6/"/>
        <id>https://mrkaran.dev/posts/load-testing-k6/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/load-testing-k6/">&lt;p&gt;This week I was occupied with optimising a Golang program I’d written at work. I wanted a way to reproduce the issue under heavy load on my development environment and Load Tests are a good way to do that.&lt;&#x2F;p&gt;
&lt;p&gt;The service in question is a RESTful API so it’s relatively easy to use any HTTP load test tools. The endpoint had an input parameter &lt;code&gt;uuid&lt;&#x2F;code&gt; which accepted a valid &lt;code&gt;UUIDv4&lt;&#x2F;code&gt; as the input. To my surprise, this was not so straightforward with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rakyll&#x2F;hey&quot;&gt;hey&lt;&#x2F;a&gt; (which is my tool of choice for simple tests) and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;CloudFundoo&#x2F;ApacheBench-ab&quot;&gt;ab&lt;&#x2F;a&gt;. While it was possible to write an external script to do that, I thought to look around at some “scriptable” alternatives. I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wg&#x2F;wrk&quot;&gt;wrk&lt;&#x2F;a&gt; which allowed me to write custom Lua modules. Now, I didn’t want to lose my focus from the main task which was load testing my service to write Lua, so I didn’t use &lt;code&gt;wrk&lt;&#x2F;code&gt; but it’s still a pretty decent option (and &lt;em&gt;very very&lt;&#x2F;em&gt; fast, at that).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hello-k6&quot;&gt;Hello k6!&lt;a class=&quot;zola-anchor&quot; href=&quot;#hello-k6&quot; aria-label=&quot;Anchor link for: hello-k6&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;k6.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Some more Google-fu resulted in me finding &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;&quot;&gt;k6&lt;&#x2F;a&gt;. I’d never heard of this but after exploring the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grafana&#x2F;k6&quot;&gt;GitHub repo&lt;&#x2F;a&gt; and the docs it looks like a pretty active project.&lt;&#x2F;p&gt;
&lt;p&gt;So, &lt;code&gt;k6&lt;&#x2F;code&gt; basically allows you to write scriptable tests which allow you to test a variety of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;using-k6&#x2F;scenarios&#x2F;&quot;&gt;scenarios&lt;&#x2F;a&gt;. The scripts are written in Javascript and treated as ES6 Modules for extensibility. &lt;code&gt;k6&lt;&#x2F;code&gt; has a concept of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;cloud&#x2F;cloud-faq&#x2F;general-questions&#x2F;#what-are-vus-virtual-users&quot;&gt;Virtual Users&lt;&#x2F;a&gt; to mimic a real-world user. Each VU runs the “script” in an isolated self-contained JS runtime using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dop251&#x2F;goja&quot;&gt;Goja&lt;&#x2F;a&gt;. Now obviously at this point, if speed is your utmost concern to generate very heavy load tests, I guess &lt;code&gt;wrk&lt;&#x2F;code&gt; is your only real choice as invoking a JS runtime inside Go won’t be super fast. But for most use-cases and people, like my case, this will just be fine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basic-usage&quot;&gt;Basic Usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#basic-usage&quot; aria-label=&quot;Anchor link for: basic-usage&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Anyway, I quickly grokked the docs and copy-pasted some examples and modified them to what I needed. I was able to run a basic load test running very quickly and admired the simplicity here. It generated some p90, p95 etc stats which were helpful to look at. Here’s a basic example of how the script looks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; http&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k6&#x2F;http&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; check&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sleep&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; Rate&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k6&#x2F;metrics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; uuidv4&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;jslib.k6.io&#x2F;k6-utils&#x2F;1.0.0&#x2F;index.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; errorRate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; Rate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;errors&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; function&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F69D50);&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F69D50);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;post&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; params&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    headers&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Content-Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;application&#x2F;x-www-form-urlencoded&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    custname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    comments&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; uuidv4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;  check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;http&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;url&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; params&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;status is 200&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; errorRate&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;  sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;To run it:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;k6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; httpbin_load.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Here &lt;code&gt;-d&lt;&#x2F;code&gt; is for the duration to run the test and &lt;code&gt;-u&lt;&#x2F;code&gt; is to specify &lt;code&gt;Virtual User&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Explanation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It’s an &lt;code&gt;HTTP POST&lt;&#x2F;code&gt; request with some form data to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;httpbin.org&#x2F;post&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;post&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;We use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;javascript-api&#x2F;jslib&#x2F;utils&#x2F;uuidv4&#x2F;&quot;&gt;uuid&lt;&#x2F;a&gt; function because the JS stdlib is &lt;em&gt;great&lt;&#x2F;em&gt; at providing basic helper methods (&#x2F;s)&lt;&#x2F;li&gt;
&lt;li&gt;We define a check for HTTP status code as 200. Later we’ll see how to add more real-world checks under heavy load.&lt;&#x2F;li&gt;
&lt;li&gt;We have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;javascript-api&#x2F;k6&#x2F;sleep-t&#x2F;&quot;&gt;sleep&lt;&#x2F;a&gt; function to pause a little bit before each iteration. This is pretty important as leaving &lt;code&gt;sleep&lt;&#x2F;code&gt; is akin to a user pressing F5 on a browser non-stop and you’d probably not want your load tests to be that aggressive. Read &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;using-k6&#x2F;test-life-cycle&#x2F;#the-default-function-life-cycle&quot;&gt;docs&lt;&#x2F;a&gt; for more info.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;❯ k6 run -d 30s -u 10 test.js                   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &#x2F;\      |‾‾| &#x2F;‾‾&#x2F;   &#x2F;‾‾&#x2F;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &#x2F;\  &#x2F;  \     |  |&#x2F;  &#x2F;   &#x2F;  &#x2F;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &#x2F;  \&#x2F;    \    |     (   &#x2F;   ‾‾\  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   &#x2F;          \   |  |\  \ |  (‾)  | &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F; __________ \  |__| \__\ \_____&#x2F; .io&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  execution: local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     script: test.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     output: -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  scenarios: (100.00%) 1 scenario, 10 max VUs, 1m0s max duration (incl. graceful stop):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           * default: 10 looping VUs for 30s (gracefulStop: 30s)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;running (0m30.6s), 00&#x2F;10 VUs, 387 complete and 0 interrupted iterations&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;default ✓ [======================================] 10 VUs  30s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     ✓ status is 200&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     checks.........................: 100.00% ✓ 387       ✗ 0   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     data_received..................: 318 kB  10 kB&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     data_sent......................: 78 kB   2.5 kB&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_blocked...............: avg=28.65ms  min=210ns    med=857ns    max=1.1s     p(90)=1.49µs   p(95)=1.68µs  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_connecting............: avg=7.77ms   min=0s       med=0s       max=301.24ms p(90)=0s       p(95)=0s      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_duration..............: avg=254.05ms min=215.63ms med=231.15ms max=826.99ms p(90)=317.33ms p(95)=325.1ms &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       { expected_response:true }...: avg=254.05ms min=215.63ms med=231.15ms max=826.99ms p(90)=317.33ms p(95)=325.1ms &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_failed................: 0.00%   ✓ 0         ✗ 387 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_receiving.............: avg=177.35µs min=39.43µs  med=170.18µs max=604.22µs p(90)=259.75µs p(95)=285.73µs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_sending...............: avg=268.41µs min=48.62µs  med=216.61µs max=7.95ms   p(90)=334.94µs p(95)=448.21µs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_tls_handshaking.......: avg=15.87ms  min=0s       med=0s       max=615.25ms p(90)=0s       p(95)=0s      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_waiting...............: avg=253.61ms min=215.34ms med=230.77ms max=826.57ms p(90)=316.98ms p(95)=324.69ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_reqs......................: 387     12.666038&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     iteration_duration.............: avg=784ms    min=717ms    med=732.43ms max=1.92s    p(90)=820.35ms p(95)=926.87ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     iterations.....................: 387     12.666038&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     vus............................: 10      min=10      max=10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     vus_max........................: 10      min=10      max=10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Things to look for:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;From the above output, I think these 2 metrics are the most important to look at:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_duration..............: avg=254.05ms min=215.63ms med=231.15ms max=826.99ms p(90)=317.33ms p(95)=325.1ms &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_reqs......................: 387     12.666038&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We see the total requests sent in 30s were &lt;code&gt;387&lt;&#x2F;code&gt; and the &lt;code&gt;p95&lt;&#x2F;code&gt; response time is &lt;code&gt;325.1ms&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing-some-real-world-scenarios&quot;&gt;Testing some real-world scenarios&lt;a class=&quot;zola-anchor&quot; href=&quot;#testing-some-real-world-scenarios&quot; aria-label=&quot;Anchor link for: testing-some-real-world-scenarios&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This was a really simple example but we can add some more scenarios to mimic real-world checks. Let’s tweak the script to&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Go from 1 to 10 users in 10s.&lt;&#x2F;li&gt;
&lt;li&gt;Stay at 10 users for 5s.&lt;&#x2F;li&gt;
&lt;li&gt;Ramp down to 1 user for the next 15s.&lt;&#x2F;li&gt;
&lt;li&gt;Have a threshold of not exceeding 500ms as p95.&lt;&#x2F;li&gt;
&lt;li&gt;Have a threshold for the count of non &lt;code&gt;200 OK&lt;&#x2F;code&gt; responses.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The above script now becomes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; http&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k6&#x2F;http&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; check&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sleep&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; Rate&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k6&#x2F;metrics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; uuidv4&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;jslib.k6.io&#x2F;k6-utils&#x2F;1.0.0&#x2F;index.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; errorRate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; Rate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;non_200_requests&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; let&lt;&#x2F;span&gt;&lt;span&gt; options&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stages&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Ramp-up from 1 to 10 VUs in 10s.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {&lt;&#x2F;span&gt;&lt;span&gt; duration&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;10s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; target&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Stay at rest on 10 VUs for 5s.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {&lt;&#x2F;span&gt;&lt;span&gt; duration&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; target&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Linearly ramp down from 10 to 0 VUs over the last 15s.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {&lt;&#x2F;span&gt;&lt;span&gt; duration&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;15s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; target&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    thresholds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; We want the 95th percentile of all HTTP request durations to be less than 500ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;http_req_duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p(95)&amp;lt;500&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Thresholds based on the custom metric `non_200_requests`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;non_200_requests&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Global failure rate should be less than 1%.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rate&amp;lt;0.01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Abort the test early if it climbs over 5%.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            {&lt;&#x2F;span&gt;&lt;span&gt; threshold&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rate&amp;lt;=0.05&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; abortOnFail&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; function&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F69D50);&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#24292E, #F69D50);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;post&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; params&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    headers&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Content-Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;application&#x2F;x-www-form-urlencoded&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    custname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    comments&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; uuidv4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;  check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;http&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;url&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; params&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;status is 200&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; errorRate&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;  sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;random&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Random sleep between 1s and 2s.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Run with &lt;code&gt;k6 run test.js&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2.21.0 on ☁️  (ap-south-1) took 24s &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;❯ k6 run test.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &#x2F;\      |‾‾| &#x2F;‾‾&#x2F;   &#x2F;‾‾&#x2F;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &#x2F;\  &#x2F;  \     |  |&#x2F;  &#x2F;   &#x2F;  &#x2F;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &#x2F;  \&#x2F;    \    |     (   &#x2F;   ‾‾\  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   &#x2F;          \   |  |\  \ |  (‾)  | &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F; __________ \  |__| \__\ \_____&#x2F; .io&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  execution: local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     script: test.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     output: -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  scenarios: (100.00%) 1 scenario, 10 max VUs, 1m0s max duration (incl. graceful stop):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           * default: Up to 10 looping VUs for 30s over 3 stages (gracefulRampDown: 30s, gracefulStop: 30s)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;running (0m30.3s), 00&#x2F;10 VUs, 105 complete and 0 interrupted iterations&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;default ✓ [======================================] 00&#x2F;10 VUs  30s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     ✓ status is 200&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     checks.........................: 100.00% ✓ 105      ✗ 0   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     data_received..................: 126 kB  4.2 kB&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     data_sent......................: 25 kB   841 B&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_blocked...............: avg=73.69ms  min=292ns    med=761ns    max=1.02s    p(90)=1.54µs   p(95)=688.76ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_connecting............: avg=21.67ms  min=0s       med=0s       max=245.46ms p(90)=0s       p(95)=223.77ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ✓ http_req_duration..............: avg=252.72ms min=215.88ms med=230.31ms max=560.17ms p(90)=299.12ms p(95)=406.94ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       { expected_response:true }...: avg=252.72ms min=215.88ms med=230.31ms max=560.17ms p(90)=299.12ms p(95)=406.94ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_failed................: 0.00%   ✓ 0        ✗ 105 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_receiving.............: avg=177.85µs min=103.82µs med=163.76µs max=366.5µs  p(90)=235.86µs p(95)=266.39µs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_sending...............: avg=258.17µs min=96.92µs  med=215.88µs max=958.67µs p(90)=410.05µs p(95)=487.18µs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_tls_handshaking.......: avg=50.22ms  min=0s       med=0s       max=614.14ms p(90)=0s       p(95)=460.3ms &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_req_waiting...............: avg=252.29ms min=215.17ms med=229.69ms max=559.86ms p(90)=298.42ms p(95)=406.52ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     http_reqs......................: 105     3.471037&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     iteration_duration.............: avg=1.84s    min=1.22s    med=1.85s    max=3.02s    p(90)=2.22s    p(95)=2.46s   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     iterations.....................: 105     3.471037&#x2F;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     vus............................: 1       min=1      max=10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     vus_max........................: 10      min=10     max=10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see that all the checks passed without breaching any thresholds we’d set.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Some important points&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In my local environment, I stress tested my service with 10k VUs which is quite a high number for the service but it was good to see it hold under extreme conditions as well. An important thing to note if you are spawning many VUs is that &lt;code&gt;ulimit&lt;&#x2F;code&gt; number should be high. This is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;misc&#x2F;fine-tuning-os&#x2F;&quot;&gt;described in their docs&lt;&#x2F;a&gt; as well.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;To debug the HTTP response you can run with &lt;code&gt;--http-debug=&quot;full&quot;&lt;&#x2F;code&gt; flag and get the verbose output for debugging.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve barely scratched the surface of what this tool does. You can export metrics to various data sources, add a lot more checks on the response code, use it with GRPC or WebSockets as well.&lt;&#x2F;p&gt;
&lt;p&gt;Overall pretty happy with this tool and I am going to use more of it for future projects.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;a class=&quot;zola-anchor&quot; href=&quot;#references&quot; aria-label=&quot;Anchor link for: references&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;blog&#x2F;comparing-best-open-source-load-testing-tools&#x2F;&quot;&gt;https:&#x2F;&#x2F;k6.io&#x2F;blog&#x2F;comparing-best-open-source-load-testing-tools&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;our-beliefs&#x2F;#simple-testing-is-better-than-no-testing&quot;&gt;https:&#x2F;&#x2F;k6.io&#x2F;our-beliefs&#x2F;#simple-testing-is-better-than-no-testing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;&quot;&gt;https:&#x2F;&#x2F;k6.io&#x2F;docs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grafana&#x2F;k6&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;grafana&#x2F;k6&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Fin&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Analyzing CoreDNS logs with Clickhouse and Vector</title>
        <published>2021-06-05T00:00:00+05:30</published>
        <updated>2021-06-05T00:00:00+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/coredns-vector-clickhouse/"/>
        <id>https://mrkaran.dev/posts/coredns-vector-clickhouse/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/coredns-vector-clickhouse/">&lt;p&gt;I’ve been toying around &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.tech&#x2F;&quot;&gt;Clickhouse&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;&quot;&gt;Vector&lt;&#x2F;a&gt; at my day job and find both of these tools pretty interesting at what they do. A short summary for those unaware of these tools:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vector&lt;&#x2F;strong&gt; helps you build a pipeline for collecting, transforming and processing different kinds of observability data (logs and metrics).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Clickhouse&lt;&#x2F;strong&gt; is a columnar based DB used as a warehousing tool for generating reports and analytics.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, for the context, I use &lt;code&gt;coredns&lt;&#x2F;code&gt; on my personal dev machine as it supports Split DNS (routing certain zones to a particular resolver) which I need for accessing internal domains at work. Yep, &lt;code&gt;systemd-resolved&lt;&#x2F;code&gt; can also do this, but I find &lt;code&gt;coredns&lt;&#x2F;code&gt; easier to configure and manage with OpenVPN as well.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, so one random evening, I got the idea of dumping CoreDNS Logs to Clickhouse. &lt;em&gt;Maaaybe&lt;&#x2F;em&gt; I was still hungover from the Vector&#x2F;Clickhouse work I was doing at work but nevertheless I was interested in it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;a class=&quot;zola-anchor&quot; href=&quot;#overview&quot; aria-label=&quot;Anchor link for: overview&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Gather logs from CoreDNS.&lt;&#x2F;li&gt;
&lt;li&gt;Transform the logs with &lt;code&gt;regex&lt;&#x2F;code&gt; and construct a payload for Clickhouse.&lt;&#x2F;li&gt;
&lt;li&gt;Write a schema for the logs table.&lt;&#x2F;li&gt;
&lt;li&gt;Dump to Clickhouse.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here’s how the pipeline looks:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;coredns-vector-ch.jpg&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;collecting-logs&quot;&gt;Collecting Logs&lt;a class=&quot;zola-anchor&quot; href=&quot;#collecting-logs&quot; aria-label=&quot;Anchor link for: collecting-logs&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;First, let’s look at how the raw logs are structured by CoreDNS:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 127.0.0.1:55678 - 21963 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN xpui.app.spotify.com. udp 38 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,rd,ra 121 0.061416978s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 127.0.0.1:59333 - 22742 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;AAAA IN incoming.telemetry.mozilla.org. udp 48 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NOERROR qr,aa,rd,ra 106 0.049235139s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 127.0.0.1:39609 - 47247 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;AAAA IN ping.archlinux.org. udp 36 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NOERROR qr,rd,ra 140 0.056721154s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Vector provides a variety of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;configuration&#x2F;sources&#x2F;&quot;&gt;sources&lt;&#x2F;a&gt; to collect these logs. Since I am running &lt;code&gt;coredns&lt;&#x2F;code&gt; as a Docker container, the following config shows how to collect logs from a particular container:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Filter coredns logs from Docker logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;coredns_logs&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; required&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  docker_host&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;unix:&#x2F;&#x2F;&#x2F;var&#x2F;run&#x2F;docker.sock&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  include_images&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns&#x2F;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; optional, no default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above config basically specifies a Docker Host variable and an image name filter. Vector talks to the Docker API over a &lt;code&gt;unix&lt;&#x2F;code&gt; socket and gathers metadata about the container (like &lt;code&gt;container_created_at&lt;&#x2F;code&gt;, &lt;code&gt;container_name&lt;&#x2F;code&gt;, &lt;code&gt;label&lt;&#x2F;code&gt; etc).&lt;&#x2F;p&gt;
&lt;p&gt;After collecting logs from Vector, it enriches with the following metadata.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;container_created_at&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2021-06-04T14:18:03.967143133Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;container_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;00c5c4d36ea5b4772b517d3cca7d397c92f72be2a2bf45bb8c430f717fbd331e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;container_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns_coredns_1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;iris&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns&#x2F;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;label&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.config-hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;928d71143c2af6553d551dbbf14140304d53f92378746454fbfeb0382a896d5b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.container-number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.oneoff&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;False&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.project.config_files&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;home&#x2F;karan&#x2F;Code&#x2F;Infra&#x2F;coredns&#x2F;hydra-vpn-compose.yml&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.project.working_dir&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;home&#x2F;karan&#x2F;Code&#x2F;Infra&#x2F;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;com.docker.compose.version&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1.29.2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;message&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;[INFO] 127.0.0.1:38266 - 20341 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN open.spotify.com. udp 34 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; NOERROR qr,rd,ra 160 0.300268123s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;source_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;stdout&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #8DDB8C);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;2021-06-04T16:13:07.454601872Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(NOTE: I am using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;configuration&#x2F;sinks&#x2F;console&#x2F;&quot;&gt;console&lt;&#x2F;a&gt; sink to dump these logs to &lt;code&gt;STDOUT&lt;&#x2F;code&gt;. It’s pretty handy for inspecting logs).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Print parsed logs to stdout&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;sinks.print&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;inputs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;encoding.codec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;json&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see from the above JSON object, Vector has transformed the log with its own Data Model. The log that we care about now is inside &lt;code&gt;.message&lt;&#x2F;code&gt; key. It’s nice to have other metadata as well.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;transforming-the-logs&quot;&gt;Transforming the logs&lt;a class=&quot;zola-anchor&quot; href=&quot;#transforming-the-logs&quot; aria-label=&quot;Anchor link for: transforming-the-logs&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Our objectives at this step:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Discard unused fields. We don’t really care about container metadata for this mini-project.&lt;&#x2F;li&gt;
&lt;li&gt;Parse the &lt;code&gt;message&lt;&#x2F;code&gt; field with &lt;code&gt;regex&lt;&#x2F;code&gt; so they can be stored in individual columns in our Clickhouse table.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, CoreDNS can emit two kinds of logs (&lt;code&gt;INFO&lt;&#x2F;code&gt; and &lt;code&gt;ERROR&lt;&#x2F;code&gt;). The error usually happens when the upstream resolver is unreachable or there’s an issue with any of the CoreDNS plugins.&lt;&#x2F;p&gt;
&lt;p&gt;We need to write regex for both cases:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;INFO&lt;&#x2F;code&gt; logs:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;\[(?P&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;level&amp;gt;[^&lt;&#x2F;span&gt;&lt;span&gt;]]+)]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;server_addr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;^:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;+):(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;server_port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span&gt;+-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;proto&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;do&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;bufsize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;]+)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;rcode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;rflags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;rsize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\.&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;coredns-regex-info.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;code&gt;ERROR&lt;&#x2F;code&gt; logs:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;\[(?P&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;level&amp;gt;ERROR&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;plugin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;errors&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;code&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;^:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;error_msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;coredns-regex-error.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Combining a bunch of other things to remove some fields and constructing the final payload, the config looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Parse coredns logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;transforms&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;parse_logs&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;remap&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;source&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;# parse the log event.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ts = .timestamp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;log,err = parse_regex(.message,r&amp;#39;\[(?P&amp;lt;level&amp;gt;[^]]+)]\s(?P&amp;lt;server_addr&amp;gt;[^:]+):(?P&amp;lt;server_port&amp;gt;\S+)\s+-\s+(?P&amp;lt;id&amp;gt;\S+)\s+&amp;quot;(?P&amp;lt;type&amp;gt;\S+)\s+(?P&amp;lt;class&amp;gt;\S+)\s+(?P&amp;lt;name&amp;gt;\S+)\s+(?P&amp;lt;proto&amp;gt;\S+)\s+(?P&amp;lt;size&amp;gt;\S+)\s+(?P&amp;lt;do&amp;gt;\S+)\s+(?P&amp;lt;bufsize&amp;gt;[^&amp;quot;]+)&amp;quot;\s+(?P&amp;lt;rcode&amp;gt;\S+)\s+(?P&amp;lt;rflags&amp;gt;\S+)\s+(?P&amp;lt;rsize&amp;gt;\S+)\s+(?P&amp;lt;duration&amp;gt;[\d\.]+).*&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;if err !=null {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    # capture the error log. If the error log also fails to get parsed, the log event is dropped.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  log = parse_regex!(.message,r&amp;#39;\[(?P&amp;lt;level&amp;gt;ERROR)]\s+(?P&amp;lt;component&amp;gt;plugin&#x2F;errors):\s+(?P&amp;lt;code&amp;gt;\S)+\s+(?P&amp;lt;name&amp;gt;\S+)\s+(?P&amp;lt;type&amp;gt;[^:]*):\s+(?P&amp;lt;error_msg&amp;gt;.*)&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;. = log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;# add timestamp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.timestamp = ts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;# remove fields we dont care about&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;del(.do)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drop_on_error&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apart from regex matching, we store the &lt;code&gt;timestamp&lt;&#x2F;code&gt; as received from Vector (since CoreDNS logs don’t contain any timestamp information). We delete some fields that we don’t care about.&lt;&#x2F;p&gt;
&lt;p&gt;Vector uses a powerful DSL (called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vector.dev&#x2F;docs&#x2F;reference&#x2F;vrl&#x2F;&quot;&gt;VRL&lt;&#x2F;a&gt;) to do such kind of transformations on the fly. It has a lot of functions to do almost any kind of transformation to your original event payload. You can invoke &lt;code&gt;vector vrl&lt;&#x2F;code&gt; from the terminal and get a shell to write the above transformations and debug quickly. It proved to be really useful when dealing with such a long regex pattern.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;storing-in-clickhouse&quot;&gt;Storing in Clickhouse&lt;a class=&quot;zola-anchor&quot; href=&quot;#storing-in-clickhouse&quot; aria-label=&quot;Anchor link for: storing-in-clickhouse&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Finally we get to the part where we need to dump these logs to our Clickhouse DB. Here’s the schema for the table where we will be storing these records:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DATABASE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; IF&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; NOT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; EXISTS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; IF&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; NOT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; EXISTS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Asia&#x2F;Kolkata&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;bufsize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; Int32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; Float64,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; Int32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;level&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; String,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;proto&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rcode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rflags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; String,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_addr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; String,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; Int32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rsize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; Int32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;  Int32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt; LowCardinality(String)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;) ENGINE &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; MergeTree&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;PARTITION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; BY&lt;&#x2F;span&gt;&lt;span&gt; toYYYYMM(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; toYYYYMMDD(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TTL &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; INTERVAL &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; WEEK&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Key things to note:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;clickhouse.tech&#x2F;docs&#x2F;en&#x2F;sql-reference&#x2F;data-types&#x2F;lowcardinality&#x2F;&quot;&gt;&lt;code&gt;LowCardinality&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is used for columns where the data is predictable to reduce the disk space used.&lt;&#x2F;li&gt;
&lt;li&gt;Clickhouse uses the sort key as the primary key if unspecified. This is the default behaviour.&lt;&#x2F;li&gt;
&lt;li&gt;TTL for the records is set to 1 week. After 1 week all the records will be purged. Since this is my dev machine, I don’t really care about a higher TTL.&lt;&#x2F;li&gt;
&lt;li&gt;This also means that the partition is never really put to use since I am partitioning by month but logs are being deleted every week. At this scale, it doesn’t really make sense to even have it, but I just included it for posterity.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;Clickhouse on Twitter &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ClickHouseDB&#x2F;status&#x2F;1401541954043887616&quot;&gt;clarified&lt;&#x2F;a&gt; that &lt;code&gt;ORDER BY timestamp&lt;&#x2F;code&gt; will have better performance in this context. Usually if your queries are “last 1h”, “last 5m” based, it is better to not store the the sort key as &lt;code&gt;YYYYMMDD&lt;&#x2F;code&gt; format.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clickhouse_twitter_post.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, we need to instruct Vector to send these logs to Clickhouse:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sinks&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;coredns_logs_clickhouse_output&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;clickhouse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  inputs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;parse_logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  compression&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;gzip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  database&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;coredns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  endpoint&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;http:&#x2F;&#x2F;localhost:8123&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  table&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  encoding&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;timestamp_format&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;unix&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  batch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;timeout_secs&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Clickhouse offers an HTTP API (which is running on port 8123 by default). Vector takes the input from the previous step (&lt;code&gt;parse_logs&lt;&#x2F;code&gt; transformation) and sends it to Clickhouse over the HTTP interface. Clickhouse stores datetimes in UNIX, so before sending the data, Vector can encode certain fields in the payload to a different data type as well (isn’t that cool 😎)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;query-examples&quot;&gt;Query Examples&lt;a class=&quot;zola-anchor&quot; href=&quot;#query-examples&quot; aria-label=&quot;Anchor link for: query-examples&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve been running this pipeline for 3-4 days, so I have a decent amount of data collected to show for the blog post.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Total Count of Queries&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; coredns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)─┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;16774&lt;&#x2F;span&gt;&lt;span&gt; │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Top Query Types&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; total,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; coredns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; total &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─total─┬─&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;─┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;9931&lt;&#x2F;span&gt;&lt;span&gt; │ A    │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;6852&lt;&#x2F;span&gt;&lt;span&gt; │ AAAA │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└───────┴──────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Top Query Names&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; total,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; coredns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; total &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─total─┬─&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;2513&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ping&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;archlinux&lt;&#x2F;span&gt;&lt;span&gt;.org.             │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1868&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ws&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;todoist&lt;&#x2F;span&gt;&lt;span&gt;.com.                 │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1011&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;telemetry&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;mozilla&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;org&lt;&#x2F;span&gt;&lt;span&gt;. │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;802&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;vortex&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;microsoft&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;com&lt;&#x2F;span&gt;&lt;span&gt;.      │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;707&lt;&#x2F;span&gt;&lt;span&gt; │ logs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;01&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;loggly&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;com&lt;&#x2F;span&gt;&lt;span&gt;.             │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└───────┴─────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Max&#x2F;Min duration&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    max&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;duration) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; max,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;duration) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; min&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; coredns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FORMAT Vertical&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;──────&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;max: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;056606352&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;min: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;000020837&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Top TLDs Queried&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; total,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    topLevelDomain(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;substring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; tld&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; coredns&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span&gt; tld&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; total &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─total─┬─tld──┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;10666&lt;&#x2F;span&gt;&lt;span&gt; │ com  │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;3950&lt;&#x2F;span&gt;&lt;span&gt; │ org  │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;671&lt;&#x2F;span&gt;&lt;span&gt; │ net  │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;346&lt;&#x2F;span&gt;&lt;span&gt; │ so   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;288&lt;&#x2F;span&gt;&lt;span&gt; │ tech │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;279&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;io&lt;&#x2F;span&gt;&lt;span&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;190&lt;&#x2F;span&gt;&lt;span&gt; │ co   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;167&lt;&#x2F;span&gt;&lt;span&gt; │ dev  │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│    &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;82&lt;&#x2F;span&gt;&lt;span&gt; │ arpa │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│    &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;43&lt;&#x2F;span&gt;&lt;span&gt; │ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└───────┴──────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Well, that’s all I could think of really. If you’ve some more interesting analysis to get from this data, let me know!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The intention behind writing this post is to give an overview of how the entire log collection and processing pipeline works. Using Vector has been an amazing experience however the sad bit is that I don’t know Rust and I cannot contribute to some of the issues I’ve opened (even though they are presumably trivial). Maybe I should pick up Rust, finally? 🤭&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How I take Notes</title>
        <published>2021-04-14T08:10:55+05:30</published>
        <updated>2021-04-14T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/how-i-take-notes/"/>
        <id>https://mrkaran.dev/posts/how-i-take-notes/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/how-i-take-notes/">&lt;p&gt;Over the past 2-3 years, note-taking apps have become all the rage. Note-taking is an extremely subjective topic and a lot of it depends on the individual’s workflow. There’s no one size fits all and maybe that justifies the ever-expanding landscape of such apps. I’ve tried a few popular ones (Notion, Roam Research) in the recent past but never really quite stuck to any after the initial hype phase.&lt;&#x2F;p&gt;
&lt;p&gt;I even collaborated with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sarat.dev&#x2F;&quot;&gt;@iamd3vil&lt;&#x2F;a&gt; to make our &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hackstream&#x2F;zettel&#x2F;&quot;&gt;own version&lt;&#x2F;a&gt; of the Zettelkasten based note-taking app. I found the Zettelkasten system to be really useful on paper but then again, I didn’t use it after a few weeks.&lt;&#x2F;p&gt;
&lt;p&gt;Tried the old school way of Bullet Journal (and I did end up liking it quite a lot) but it was not so practical in many cases (like documenting code snippets, URLs etc).&lt;&#x2F;p&gt;
&lt;p&gt;Disgruntled with all the options, I just had a simple folder on my laptop with some markdown files in it. It was a stop-gap solution until I found something better.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;&#x2F;strong&gt;: I’ve been through a pendulum phase of finding a new note-taking app, wasting time to set it up the “proper way” and then just end up not using it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enter-joplin&quot;&gt;Enter Joplin&lt;a class=&quot;zola-anchor&quot; href=&quot;#enter-joplin&quot; aria-label=&quot;Anchor link for: enter-joplin&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;joplin-desktop.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;shantanugoel.com&quot;&gt;@shantanugoel&lt;&#x2F;a&gt; who introduced me to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;joplinapp.org&#x2F;&quot;&gt;Joplin&lt;&#x2F;a&gt;. He’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;shantanugoel.com&#x2F;2020&#x2F;03&#x2F;20&#x2F;hammerspoon-backup-joplin-notes-dotfiles-git-macos&#x2F;&quot;&gt;heavy user&lt;&#x2F;a&gt; of it as well and that gave me some confidence to try it out. I initially disliked it because of &lt;em&gt;not-so-great-looking&lt;&#x2F;em&gt; UI theme and how it essentially looked &lt;em&gt;just&lt;&#x2F;em&gt; an editor. Admittedly, I was proven wrong quickly in my initial judgement. As I gave more time to it, I noticed I kept coming back to Joplin “naturally” and stuck through it because it’s so damn simple to use. Notion, for people who have tried it would know it complicates a lot of simple tasks. You need to create databases to render a simple table, every component is a “block” (a new page) and yes it’s slow (although they are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.notion.so&#x2F;notion&#x2F;Focus-on-performance-reliability-89f937a6ccc04905b1dcfa878537e08d&quot;&gt;working on it to make it better&lt;&#x2F;a&gt;, just to be fair). Notion focuses a lot on team collaboration features, which I didn’t need for my “personal” note-taking system.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;&#x2F;strong&gt;: Joplin is fast, it’s open-source, it’s based on Markdown, and it’s simple to use. A tool you just forget that it exists, because it becomes a natural extension to your workflow. It has a great plugin system that you can use to extend it and build your own utilities on top of it. The search is based on &lt;code&gt;sqlite3&lt;&#x2F;code&gt; FTS which is pretty awesome!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;workflow&quot;&gt;Workflow&lt;a class=&quot;zola-anchor&quot; href=&quot;#workflow&quot; aria-label=&quot;Anchor link for: workflow&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Joplin revolves around the concept of &lt;strong&gt;notebooks&lt;&#x2F;strong&gt;. Notebooks are broader categories for your content and you can nest multiple subnotebooks for specific categories.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve the following notebooks and subnotebooks in my Joplin setup:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Bookmarks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Twitter Threads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - HN Threads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Articles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Design Inspo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Youtube Videos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Inbox&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Links&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Adhoc Notes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Personal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Finance&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Dev Setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - OSS Ideas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Self Hosted Setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Org-Stuff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - Redacted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Over the week, I primarily use the &lt;code&gt;Inbox&#x2F;Adhoc Notes&lt;&#x2F;code&gt; notebook as a brain dump. I don’t focus much on the structure, the aim is to get the content out and stored. I’m also someone who doesn’t like to keep more than 5 browser tabs open at any time, so I use &lt;code&gt;Links&lt;&#x2F;code&gt; notebook with Joplin’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;joplinapp.org&#x2F;clipper&#x2F;&quot;&gt;Web Clipper&lt;&#x2F;a&gt; service to store these links to read later.&lt;&#x2F;p&gt;
&lt;p&gt;Every weekend, I clean up these notebooks to achieve “Inbox Zero”. The idea is to move all these ad-hoc notes to their proper notebooks, annotated with tags. All the useful links are moved in the appropriate &lt;code&gt;Bookmarks&#x2F;...&lt;&#x2F;code&gt; notebook as well. This helps me find stuff quicker at a later time.&lt;&#x2F;p&gt;
&lt;p&gt;I heavily use Tags in all my notebooks, which allows me to have a unified view of different kind of stuff I’ve. For example “golang” tag in my Work notes and Personal notes, allows me to see all the “golang” stuff together in one place.&lt;&#x2F;p&gt;
&lt;p&gt;For stuff that can be shared publicly, I basically copy-paste those notes in my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;notes.mrkaran.dev&#x2F;&quot;&gt;public wiki&lt;&#x2F;a&gt; as well. This allows me to share snippets&#x2F;commands with others, which Joplin cannot do.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;synchronisation&quot;&gt;Synchronisation&lt;a class=&quot;zola-anchor&quot; href=&quot;#synchronisation&quot; aria-label=&quot;Anchor link for: synchronisation&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Joplin provides a bunch of different &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;joplinapp.org&#x2F;#synchronisation&quot;&gt;sync&lt;&#x2F;a&gt; options. I’ve tried Dropbox, Nextcloud and AWS S3 targets in the past but off late there’s a new sync option, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;laurent22&#x2F;joplin&#x2F;blob&#x2F;dev&#x2F;packages&#x2F;server&#x2F;README.md&quot;&gt;Joplin Server&lt;&#x2F;a&gt; which provides native sync for Joplin files. I found this option to be the best so far because Dropbox&#x2F;OneNote etc have API limits and syncing on an initial device with lots of notes will be time-consuming.&lt;&#x2F;p&gt;
&lt;p&gt;I self-host this Joplin Sync Server on my server and have configured the Android app and the Desktop app to use this server endpoint as the sync &lt;code&gt;target&lt;&#x2F;code&gt;. So far so good, although it’s relatively a newer sync option so it’s pertinent to have alternate backups.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;backups-and-export&quot;&gt;Backups and Export&lt;a class=&quot;zola-anchor&quot; href=&quot;#backups-and-export&quot; aria-label=&quot;Anchor link for: backups-and-export&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Joplin stores all the files locally on a device in a &lt;code&gt;sqlite3&lt;&#x2F;code&gt; DB. It can export notes in markdown&#x2F;HTML format however the file names are all named with the &lt;code&gt;id&lt;&#x2F;code&gt; of the note (and not really the title of the note). I found this to be a bit of a drawback, however, one can quickly whip up a small Python script to fix this using the Joplin API.&lt;&#x2F;p&gt;
&lt;p&gt;Joplin also has the option to export all of the notes and notebooks with their metadata (Geolocation, creation time etc), tags in a custom format called Joplin Export File (JEX). This option is pretty convenient to re-import in a new Joplin installation as well.&lt;&#x2F;p&gt;
&lt;p&gt;Sidenote for people using Joplin Server: Once https:&#x2F;&#x2F;github.com&#x2F;laurent22&#x2F;joplin&#x2F;issues&#x2F;4836 gets resolved, it’ll be possible to do &lt;code&gt;joplin sync&lt;&#x2F;code&gt; and cron it, just like other sync targets.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;support&quot;&gt;Support&lt;a class=&quot;zola-anchor&quot; href=&quot;#support&quot; aria-label=&quot;Anchor link for: support&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Joplin is 100% FOSS and is actively developed by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;laurent22&#x2F;&quot;&gt;&lt;code&gt;@laurent22&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and a few other regular contributors. I contribute &lt;code&gt;$5&#x2F;mo&lt;&#x2F;code&gt; to laurent22 via Github Sponsors. It’s more or less the same amount that most note-taking apps charge for personal use as well, so this is just me expressing gratitude for building such a lovely software for the world to use it. I’m not sure of the motivations of &lt;code&gt;laurent22&lt;&#x2F;code&gt; behind building this and I don’t wanna incorrectly assume anything either, but I guess some amount of financial incentive makes the whole deal sustainable for the open-source ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading! It’s been around a year that I am using Joplin and I posted this blog post only after really really using it a lot.&lt;&#x2F;p&gt;
&lt;p&gt;I’d love to know about your note-taking setups too, so please reach out to me on the usual channels that I’m available on and feel free to discuss!&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
&lt;h4 id=&quot;bonus-section-why-not-obsidian&quot;&gt;(Bonus Section) Why Not Obsidian&lt;a class=&quot;zola-anchor&quot; href=&quot;#bonus-section-why-not-obsidian&quot; aria-label=&quot;Anchor link for: bonus-section-why-not-obsidian&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Yes, Obsidian is comparable to Joplin in a lot of ways. However there’s a term in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;obsidian.md&#x2F;eula&quot;&gt;license&lt;&#x2F;a&gt; of Obsidian for personal use that makes it &lt;strong&gt;impossible&lt;&#x2F;strong&gt; to use it for your work stuff:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;You need to pay for Obsidian if and only if you use it for revenue-generating, work-related activities in a company that has two or more people. Get a commercial license for each user if that’s the case&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I don’t have a problem for “paying” for software but such kinda licenses are just BS.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Running Nomad for home server</title>
        <published>2021-02-14T08:10:55+05:30</published>
        <updated>2021-02-14T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/home-server-nomad/"/>
        <id>https://mrkaran.dev/posts/home-server-nomad/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/home-server-nomad/">&lt;p&gt;It’s been a long time since I’ve written a post on Hydra (my home server). I use Hydra as a testbed to learn new tools, workflows and it just gives me joy to self-host applications while learning something in return.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;history&quot;&gt;History&lt;a class=&quot;zola-anchor&quot; href=&quot;#history&quot; aria-label=&quot;Anchor link for: history&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A brief history of how &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;hydra&quot;&gt;Hydra’s&lt;&#x2F;a&gt; setup evolved over time:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;home-server-setup&#x2F;&quot;&gt;2019&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A pretty minimal K3s setup deployed on 2 RPi4 nodes. I couldn’t continue with this setup because:
&lt;ul&gt;
&lt;li&gt;Some of the apps didn’t have ARM-based image (this was 2019, pre M1 hype era).&lt;&#x2F;li&gt;
&lt;li&gt;Didn’t want to risk deploying persistent workloads on RPi.&lt;&#x2F;li&gt;
&lt;li&gt;A lot of tooling to deploy workloads was missing (storing env variables for eg.).&lt;&#x2F;li&gt;
&lt;li&gt;It was so boring to write YAML (that I also did at work). Didn’t give me joy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;home-server-updates&#x2F;&quot;&gt;2020 First Half&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;RPi 2x Nodes + K3s + DO Droplet. Tailscale for networking.
&lt;ul&gt;
&lt;li&gt;This was a considerable step up from the previous setup. I deployed a DO node and added &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;assign-pods-nodes&#x2F;&quot;&gt;Node Labels&lt;&#x2F;a&gt; to deploy persistent workloads on DO Node only.&lt;&#x2F;li&gt;
&lt;li&gt;I used my own tooling &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;kubekutr&#x2F;&quot;&gt;Kubekutr&lt;&#x2F;a&gt; + Kustomize which helped with version control of my configs.&lt;&#x2F;li&gt;
&lt;li&gt;Took quite a bit of time to onboard new services. Got lazy, didn’t host much apart from initial 3-4 applications.&lt;&#x2F;li&gt;
&lt;li&gt;Writing long YAMLs. No joy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;2020 Second Half:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Single node on DO. Terraform for deploying Docker containers.
&lt;ul&gt;
&lt;li&gt;I believe the third iteration nailed it for me. I kept the setup super simple, used Terraform for deploying workloads as Docker containers.&lt;&#x2F;li&gt;
&lt;li&gt;Used Terraform extensively for setting up the node, Cloudflare records, DO firewall rules.&lt;&#x2F;li&gt;
&lt;li&gt;Time to onboard new services reduced from a couple of hours to a few minutes. This was a huge win for me. I deployed around 10-15 new services to try it out on the server directly.&lt;&#x2F;li&gt;
&lt;li&gt;Writing HCL is actually a much better experience than YAML.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;why-nomad&quot;&gt;Why Nomad&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-nomad&quot; aria-label=&quot;Anchor link for: why-nomad&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nomad-hydra.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Around a month back, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nadh.in&#x2F;&quot;&gt;Kailash&lt;&#x2F;a&gt; had asked about feedback on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;&quot;&gt;Nomad&lt;&#x2F;a&gt;. We at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zerodha.com&#x2F;&quot;&gt;Zerodha&lt;&#x2F;a&gt; (India’s largest stock broker) are evaluating it to migrate our services to Nomad from Kubernetes (more on this later). It was almost 2 years since I last saw Nomad so it was definitely worth re-evaluating (esp since it hit 1.0 recently). I wanted to try out Nomad to answer a personal curiosity: &lt;em&gt;What does it do differently than Kubernetes?&lt;&#x2F;em&gt; No better way than actually getting hands dirty, right?!&lt;&#x2F;p&gt;
&lt;p&gt;After following the brief tutorials from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;learn.hashicorp.com&#x2F;nomad&quot;&gt;official website&lt;&#x2F;a&gt; I felt confident to try it for actual workloads. In my previous setup, I was hosting quite a few applications (Pihole, Gitea, Grafana etc) and thought it’ll be a nice way to learn how Nomad works by deploying the same services in the Nomad cluster. And I came in with zero expectations, I already had a nice setup which was reliable and running for me. My experience with a local Nomad cluster was joyful, I was able to quickly go from 0-&amp;gt;1 in less than 30 minutes. This BTW is a strong sign of how easy Nomad is to get started with as compared to K8s. The sheer amount of different concepts you’ve to register in your mind before you can even deploy a single container in a K8s cluster is bizarre. Nomad takes the easy way out here and simplified the concepts for developers into just three things:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;job&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  \_ group&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        \_ task&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Job: Job is a collection of different groups. Job is where the constraints for type of scheduler, update strategies and ACL is placed.&lt;&#x2F;li&gt;
&lt;li&gt;Group: Group is a collection of different tasks. A group is always executed on the same Nomad client node. You’ll want to use Groups for use-cases like a logging sidecar, reverse proxies etc.&lt;&#x2F;li&gt;
&lt;li&gt;Task: Atomic unit of work. A task in Nomad can be running a container&#x2F;binary&#x2F;Java VM etc, defining the mount points, env variables, ports to be exposed etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you’re coming from K8s you can think of Task as a Pod and Group as a Replicaset. There’s no equivalent to Job in K8s. BUT! The coolest part? You don’t have to familiarise yourself with all different types of Replicasets (Deployments, Daemonsets, Statefulsets) and different ways of configuring them.&lt;&#x2F;p&gt;
&lt;p&gt;Want to make a normal job as a periodic job in Nomad? Simply add the following block to your existing Job:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;periodic&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  cron&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;@daily&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You want to make a service run as a batch job (on all Nomad nodes – the equivalent of Daemonset in K8s)? Simply make the following change to your existing job:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);background-color: light-dark(#FFEEF0, #5D0F12);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B31D28, #FF938A);background-color: light-dark(#FFEEF0, #5D0F12);&quot;&gt;type=&amp;quot;service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);background-color: light-dark(#F0FFF4, #113417);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);background-color: light-dark(#F0FFF4, #113417);&quot;&gt;type=&amp;quot;batch&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You see &lt;strong&gt;this&lt;&#x2F;strong&gt; is what I mean by the focus on UX. There are many many such examples which will leave a nice smile on your face if you’re coming from K8s background.&lt;&#x2F;p&gt;
&lt;p&gt;I’d recommend reading &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;internals&#x2F;architecture&quot;&gt;Internal Architecture&lt;&#x2F;a&gt; of Nomad if you want to understand this in-depth.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;a class=&quot;zola-anchor&quot; href=&quot;#architecture&quot; aria-label=&quot;Anchor link for: architecture&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Tech stack for Hydra:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Tailscale VPN: Serves as a mesh layer between my laptop&#x2F;mobile and DO server. Useful for exposing internal services.&lt;&#x2F;li&gt;
&lt;li&gt;Caddy for reverse proxying and automatic SSL setup for all services. I run 2 instances of Caddy:
&lt;ul&gt;
&lt;li&gt;Internal: Listens on Tailscale Network Interface. Reverse proxies all private services.&lt;&#x2F;li&gt;
&lt;li&gt;Public: Listens on DO’s Public IPv4 network interface. Reverse proxies all public-facing services.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Terraform: Primary component to have IaC (Infra as Code). Modules to manage:
&lt;ul&gt;
&lt;li&gt;Cloudflare DNS Zone and Records&lt;&#x2F;li&gt;
&lt;li&gt;DO Droplet, Firewall rules, SSH Keys, Floating IPs etc.&lt;&#x2F;li&gt;
&lt;li&gt;Nomad Jobs. Used for running workloads after templating env variables, config files in Nomad job files.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;complexity-of-nomad-vs-kubernetes&quot;&gt;Complexity of Nomad vs Kubernetes&lt;a class=&quot;zola-anchor&quot; href=&quot;#complexity-of-nomad-vs-kubernetes&quot; aria-label=&quot;Anchor link for: complexity-of-nomad-vs-kubernetes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&#x2F;status&#x2F;1268762357355823104&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;k8s-meme.jpeg&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nomad shines because it follows the UNIX philosophy of “Make each program do one thing well”. To put simply, Nomad is &lt;em&gt;just&lt;&#x2F;em&gt; a workload orchestrator. It only is concerned about things like Bin Packing, scheduling decisions.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re running heterogeneous workloads, running a server (or a set of servers) quickly becomes expensive. Hence orchestrators tend to make sense in this context. They tend to save costs by making it efficient to run a vast variety of workloads. This is all an orchestrator has to do really.&lt;&#x2F;p&gt;
&lt;p&gt;Nomad doesn’t interfere in your DNS setup, Service Discovery, secrets management mechanisms and pretty much anything else. If you read some of the posts at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k8s.af&#x2F;&quot;&gt;Kubernetes Failure Stories&lt;&#x2F;a&gt;, the most common reason for outages is Networking (DNS, ndots etc). A lot of marketing around K8s never talks about these things.&lt;&#x2F;p&gt;
&lt;p&gt;I always maintain “Day 0 is easy, Day N is the real test of your skills”. Anyone can deploy a workload to a K8s cluster, it’s always the Day N operations which involve debugging networking drops, mysterious container restarts, proper resource allocations and other such complex issues that require real skills &lt;strong&gt;and&lt;&#x2F;strong&gt; effort. It’s not as easy as &lt;code&gt;kubectl apply -f&lt;&#x2F;code&gt; and my primary gripe is with people who miss out on this in their “marketing” pitches (obvious!).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-to-use-nomad&quot;&gt;When to use Nomad&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-to-use-nomad&quot; aria-label=&quot;Anchor link for: when-to-use-nomad&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Nomad hits the sweet spot of being operationally easy and functional. Nomad is a great choice if you want to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Run not just containers but other forms of workloads.&lt;&#x2F;li&gt;
&lt;li&gt;Increase developer productivity by making it easier to deploy&#x2F;onboard new services.&lt;&#x2F;li&gt;
&lt;li&gt;Consistent experience of deployment by testing the deployments locally.&lt;&#x2F;li&gt;
&lt;li&gt;(Not joking) You are tired of running Helm charts or writing large YAML manifests. The config syntax for Nomad jobs is human friendly and easy to grasp.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Nomad is available as a single binary. If you want to try it locally, all you need is &lt;code&gt;sudo nomad agent -dev&lt;&#x2F;code&gt; and you’ll have a Nomad Server, Client running in dev mode along with a UI. This makes it easy for the developers to test out the deployments locally because there’s very little configuration difference between this and production deployment. Not to forget it’s super easy to self-host Nomad clusters. I’m yet to meet anyone who self hosts K8s clusters in production without a dedicated team babysitting it always.&lt;&#x2F;p&gt;
&lt;p&gt;Once you eliminate the “blackbox” components from your stack, life becomes easier for everyone.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-to-not-use-nomad&quot;&gt;When to not use Nomad&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-to-not-use-nomad&quot; aria-label=&quot;Anchor link for: when-to-not-use-nomad&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;If you’re relying on custom controllers and operators. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;extend-kubernetes&#x2F;operator&#x2F;&quot;&gt;Operator Pattern&lt;&#x2F;a&gt; is a new way of managing large complex distributed systems (like databases, job queues etc). There are a lot of community built operators which help in reducing the effort to run these services. However, all of these are tied deeply into the “Kubernetes” ecosystem. If you find yourself running any of such operators, it’ll be tough (not impossible) to translate the same in Nomad ecosystem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I &lt;em&gt;genuinely&lt;&#x2F;em&gt; cannot think of any other reason to not use Nomad!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;practical-scenarios&quot;&gt;Practical Scenarios&lt;a class=&quot;zola-anchor&quot; href=&quot;#practical-scenarios&quot; aria-label=&quot;Anchor link for: practical-scenarios&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since I migrated a couple of workloads from my DO docker containers setup to Nomad, I’d demonstrate a few use cases which might be helpful if you want to start migrating your services to Nomad&lt;&#x2F;p&gt;
&lt;h3 id=&quot;accessing-a-web-service-with-reverse-proxy&quot;&gt;Accessing a Web service with Reverse Proxy&lt;a class=&quot;zola-anchor&quot; href=&quot;#accessing-a-web-service-with-reverse-proxy&quot; aria-label=&quot;Anchor link for: accessing-a-web-service-with-reverse-proxy&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Context: I’m running Caddy as a reverse proxy for all the services. Since we discussed earlier, Nomad &lt;strong&gt;only&lt;&#x2F;strong&gt; is concerned about scheduling, so how exactly do you do Service Discovery? You need Consul (or something like Consul, Nomad has no hard restrictions) to register a service name with it’s IP Address. Here’s how you can do that:&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;code&gt;.task&lt;&#x2F;code&gt; section of your Nomad job spec, you need to register the service name with the port you’re registering and additional tags as metadata (optional):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;gitea-web&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;gitea&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;http&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nomad’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;job-specification&#x2F;template&quot;&gt;template&lt;&#x2F;a&gt; uses &lt;code&gt;consul-template&lt;&#x2F;code&gt; behind the scenes. This is a small utility which continuously watches for Consul&#x2F;Vault keys and provides the ability to reload&#x2F;restart your workloads if any of those keys change. It can also be used to &lt;em&gt;discover&lt;&#x2F;em&gt; the address of the service registered in Consul. So here’s an example of &lt;code&gt;Caddyfile&lt;&#x2F;code&gt; using Consul Template functions to pull the IP address of the upstream &lt;code&gt;gitea-web&lt;&#x2F;code&gt; service:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;mrkaran&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;dev&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; range service &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;gitea-web&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    reverse_proxy &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; .Address &lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; .Port &lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; end &lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When a job is submitted to Nomad, a rendered template is mounted inside the container. You can define actions on what to do when the values change. For eg on a redeployment of Gitea container, the address will most likely change. We’d like Caddy to automatically restart with the new address configured in the Caddyfile in that case:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;caddyfile_public&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  destination&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;configs&#x2F;Caddyfile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Rendered template.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  change_mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;restart&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;job-specification&#x2F;template#change_mode&quot;&gt;&lt;code&gt;change_mode&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; we can either send a &lt;code&gt;signal&lt;&#x2F;code&gt; or restart the task altogether.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;binding-to-different-network-interfaces&quot;&gt;Binding to different network interfaces&lt;a class=&quot;zola-anchor&quot; href=&quot;#binding-to-different-network-interfaces&quot; aria-label=&quot;Anchor link for: binding-to-different-network-interfaces&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I run a public instance of Gitea but I wanted to restrict the SSH access only to my Tailscale network. Nomad has an interesting feature &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;docs&#x2F;job-specification&#x2F;network#host_network&quot;&gt;&lt;code&gt;host_network&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which lets you bind different ports of a task on different network interfaces.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;network&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;http&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 3000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;ssh&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 22&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Need a static assignment for SSH ops.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    static&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 4222&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; SSH port on the host only exposed to Tailscale IP.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    host_network&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;tailscale&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;templating-env-variables&quot;&gt;Templating Env Variables&lt;a class=&quot;zola-anchor&quot; href=&quot;#templating-env-variables&quot; aria-label=&quot;Anchor link for: templating-env-variables&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;&#x2F;strong&gt;: This is &lt;strong&gt;not&lt;&#x2F;strong&gt; recommended for production.&lt;&#x2F;p&gt;
&lt;p&gt;Nomad doesn’t have any templating functionalities, so all the config must be sourced from Consul and secrets should be sourced from Vault. However in the time constraint I had, I wanted to understand Nomad and Consul better and use Vault at a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;hydra&#x2F;blob&#x2F;master&#x2F;docs&#x2F;SETUP.md#vault&quot;&gt;later stage&lt;&#x2F;a&gt;. I needed a way to interpolate the env variables. This is where Terraform comes into picture:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;nomad_job&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;app&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  jobspec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; templatefile&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;conf&#x2F;shynet.nomad&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    shynet_django_secret_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; var.shynet_django_secret_key,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    shynet_postgresql_password&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; var.shynet_postgresql_password&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  hcl2&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    enabled&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can pass the variables from Terraform (which can be sourced by &lt;code&gt;TF_VAR_&lt;&#x2F;code&gt; in your local env) to the Nomad job spec. Inside the job spec we can use &lt;code&gt;env&lt;&#x2F;code&gt; to make it available to our task:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DB_PASSWORD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;              =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;shynet_postgresql_password&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DJANGO_SECRET_KEY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;shynet_django_secret_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;running-a-backup-job-on-the-host&quot;&gt;Running a backup job on the host&lt;a class=&quot;zola-anchor&quot; href=&quot;#running-a-backup-job-on-the-host&quot; aria-label=&quot;Anchor link for: running-a-backup-job-on-the-host&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I use &lt;code&gt;restic&lt;&#x2F;code&gt; to take periodic backups of my server and upload to Backblaze B2. Since Nomad supports running tasks as a different isolated environment (&lt;code&gt;chroot&lt;&#x2F;code&gt;) using &lt;code&gt;exec&lt;&#x2F;code&gt; driver and even without isolation using &lt;code&gt;raw_exec&lt;&#x2F;code&gt; driver, I wanted to give that a try. I’ve to resort using &lt;code&gt;raw_exec&lt;&#x2F;code&gt; driver here because &lt;code&gt;&#x2F;data&lt;&#x2F;code&gt; file path on my host was not available to the chroot’ed environment.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;hcl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;restic&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  datacenters&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;hydra&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  periodic&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cron&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;             =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0 3 * * *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    time_zone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Asia&#x2F;Kolkata&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    prohibit_overlap&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  task&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; &amp;quot;backup&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	  driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;raw_exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	  config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Since `&#x2F;data` is owned by `root`, restic needs to be spawned as `root`. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; `raw_exec` spawns the process with which `nomad` client is running (`root` i.e.).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$${NOMAD_TASK_DIR}&#x2F;restic_backup.sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can follow the rest of the config &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;hydra&#x2F;blob&#x2F;master&#x2F;terraform&#x2F;modules&#x2F;restic&#x2F;conf&#x2F;restic.nomad&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scope-of-improvements&quot;&gt;Scope of Improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#scope-of-improvements&quot; aria-label=&quot;Anchor link for: scope-of-improvements&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Nomad has been an absolute joy to work with. However, I’ve spotted a few rough edge cases which I believe one should be aware of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;host_network&lt;&#x2F;code&gt; property sometimes gets ignored when doing a modification to &lt;code&gt;service&lt;&#x2F;code&gt;. I’ve opened an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;10001&quot;&gt;issue&lt;&#x2F;a&gt; upstream but looks like other people are facing similar behaviours &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;10016&quot;&gt;here&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;9006&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;host_network&lt;&#x2F;code&gt; as of present &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;8577&quot;&gt;cannot&lt;&#x2F;a&gt; bind to a floating IP address (DigitalOcean&#x2F;GCP etc). I’ve to resort to using my droplet’s public IPv4 address for now.&lt;&#x2F;li&gt;
&lt;li&gt;I tried using Consul Connect (service mesh with mTLS) but looks like again because of &lt;code&gt;host_network&lt;&#x2F;code&gt;, I’m &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;9683&quot;&gt;unable&lt;&#x2F;a&gt; to use it.&lt;&#x2F;li&gt;
&lt;li&gt;Nomad CLI can definitely be &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;9441&quot;&gt;improved&lt;&#x2F;a&gt; for a much more consistent experience. I particularly missed using &lt;code&gt;kubectl&lt;&#x2F;code&gt; when using &lt;code&gt;nomad&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That apart, I ended up sending a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;pull&#x2F;10026&quot;&gt;PR&lt;&#x2F;a&gt; to upstream addressing a CLI arg ordering issue.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gotchas&quot;&gt;Gotchas:&lt;a class=&quot;zola-anchor&quot; href=&quot;#gotchas&quot; aria-label=&quot;Anchor link for: gotchas&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;On a Nomad server &lt;em&gt;already&lt;&#x2F;em&gt; bootstrapped, if you try changing &lt;code&gt;server.bind_addr&lt;&#x2F;code&gt;, it won’t have any effect. I almost pulled my hair debugging this, ultimately deleting the &lt;code&gt;data_dir&lt;&#x2F;code&gt; of the server resolved the issue for me.&lt;&#x2F;li&gt;
&lt;li&gt;I’m running DB &lt;em&gt;and&lt;&#x2F;em&gt; the App together as a single “group” in my setup configs. Don’t do this in production. Whenever you restart the job, the group will restart both the containers. The side effect of this is pretty interesting: Since we use Consul to fetch the DB Host, the app may start before the DB boots up &lt;em&gt;and&lt;&#x2F;em&gt; registers its new address with Consul. I will fix the dependency in a future version but since I’m running fewer workloads and there are automatic retries, it’s okay enough for me to keep it like this.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;community&quot;&gt;Community&lt;a class=&quot;zola-anchor&quot; href=&quot;#community&quot; aria-label=&quot;Anchor link for: community&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Nomad’s community is pretty small compared to Kubernetes. However, the folks are super responsive on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitter.im&#x2F;hashicorp-nomad&#x2F;Lobby&quot;&gt;Gitter&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discuss.hashicorp.com&#x2F;&quot;&gt;Discourse&lt;&#x2F;a&gt; and Github Issues. A few noteworthy mentions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;the-maldridge&quot;&gt;@the-maldridge&lt;&#x2F;a&gt; helped me with my doubts in Gitter.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tgross&quot;&gt;@tgross&lt;&#x2F;a&gt; who is super responsive on Github issues and does an excellent job at housekeeping the issues.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;shantanugadgil&quot;&gt;@shantanugadgil&lt;&#x2F;a&gt; who is also pretty active in the community.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Nomad’s ecosystem is still in its nascent stage and I believe there are a lot of contribution opportunities for folks interested in Golang, Ops, Distributed Systems to contribute to Nomad. The codebase of Nomad is approachable and there are quite a few key areas which can be contributed to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Docs: More examples, practical use cases.&lt;&#x2F;li&gt;
&lt;li&gt;Nomad Job files: There are many helm charts available to follow best practices. Something similar in Nomad will definitely be interesting.&lt;&#x2F;li&gt;
&lt;li&gt;Nomad Gotchas: Since K8s is widely used and has a much larger adoption, it’s only natural that the failure stories of K8s are highlighted a lot. Nomad being a pretty smaller community, we need more debugging and “things that went wrong” reference materials. You learn more from failures than 101 setup guides :)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I think I’m &lt;em&gt;sold&lt;&#x2F;em&gt; on Nomad. I’ve used Kubernetes in prod for 2 years but if you were to ask me to write a Deployment spec from scratch (without Googling&#x2F;kubectl help) I won’t be able to. After writing Nomad configs, I just can’t think of the sheer amount of boilerplate that K8s requires to get an application running.&lt;&#x2F;p&gt;
&lt;p&gt;Nomad is also a simpler piece to keep in your tech stack. Sometimes it’s best to keep things simple when you don’t really achieve any benefits from the complexity.&lt;&#x2F;p&gt;
&lt;p&gt;Nomad offers &lt;em&gt;less&lt;&#x2F;em&gt; than Kubernetes and it’s a feature, not a bug.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
&lt;h4 id=&quot;discussions&quot;&gt;Discussions&lt;a class=&quot;zola-anchor&quot; href=&quot;#discussions&quot; aria-label=&quot;Anchor link for: discussions&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=26142005&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;bybybm&#x2F;running_nomad_for_home_server&quot;&gt;Lobster&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mitchellh&#x2F;status&#x2F;1361361025568698368&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Setup Gitlab Runner with AWS ECR</title>
        <published>2021-01-29T08:10:55+05:30</published>
        <updated>2021-01-29T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/gitlab-runner-ecr/"/>
        <id>https://mrkaran.dev/posts/gitlab-runner-ecr/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/gitlab-runner-ecr/">&lt;p&gt;There are some things you expect to just work. Sadly trying to make &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;runner&#x2F;&quot;&gt;Gitlab Runner&lt;&#x2F;a&gt; with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ecr&#x2F;&quot;&gt;AWS ECR&lt;&#x2F;a&gt; turned out to be quite a daunting task and the little documentation in this area doesn’t help. There’s even a 4 years old &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-runner&#x2F;-&#x2F;issues&#x2F;1583&quot;&gt;issue&lt;&#x2F;a&gt; and everyone there is echoing the sentiment that this is unnecessarily a lot harder than it should have been.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, since I spent a lot of time figuring out how to make a Private Registry work with a cross-account ECR, I’m documenting these steps hoping it’ll help someone someday :).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-problem&quot;&gt;The Problem&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-problem&quot; aria-label=&quot;Anchor link for: the-problem&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;There are mainly 2 seemingly same but different problems when it comes to using ECR. Let’s discuss both of them separately:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pulling a private image from ECR using the Docker Executor. For eg, if your &lt;code&gt;gitlab-ci.yml&lt;&#x2F;code&gt; looks like:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;est-pull&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;PRIVATE_ECR_IMAGE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;cript&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cho &amp;quot;Hello World!&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case, the Docker Executor needs to be “authenticated” to AWS ECR so that it can pull &lt;code&gt;$PRIVATE_ECR_IMAGE&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pulling a private image &lt;em&gt;inside&lt;&#x2F;em&gt; the job. For eg, if you’re using Kaniko:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ocker-build&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cr.io&#x2F;kaniko-project&#x2F;executor:debug&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;cript&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      &#x2F;kaniko ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      # Inside this step, we use a PRIVATE_ECR_IMAGE defined in our `Dockerfile`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GoogleContainerTools&#x2F;kaniko&#x2F;&quot;&gt;Kaniko&lt;&#x2F;a&gt; needs to be “authenticated” to AWS ECR so that it can pull &lt;code&gt;$PRIVATE_ECR_IMAGE&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;&#x2F;strong&gt; I prefer Kaniko over &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;ci&#x2F;docker&#x2F;using_docker_build.html&quot;&gt;DIND&lt;&#x2F;a&gt; as it is faster, doesn’t require running the privileged container, caching is simplified, and is in general a lot simpler to setup.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-solution&quot;&gt;The Solution&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-solution&quot; aria-label=&quot;Anchor link for: the-solution&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;So, for the first case, where you want to authenticate the Docker Executor to AWS ECR, you’ll need 2 things:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Setup &lt;code&gt;DOCKER_AUTH_CONFIG&lt;&#x2F;code&gt; environment variable to  &lt;code&gt;{ &quot;credsStore&quot;: &quot;ecr-login&quot; }&lt;&#x2F;code&gt; in the &lt;code&gt;config.toml&lt;&#x2F;code&gt; of the runner. For eg:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[runners]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name = &amp;quot;Test&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  url = &amp;quot;https:&#x2F;&#x2F;gitlab.internal&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  token = &amp;quot;REDACTED&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  executor = &amp;quot;docker&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  environment = [&amp;quot;DOCKER_AUTH_CONFIG={ \&amp;quot;credsStore\&amp;quot;: \&amp;quot;ecr-login\&amp;quot; }&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Now, we’ve specified the Credential Store for Docker, but we don’t have this binary &lt;code&gt;docker-credential-ecr-login&lt;&#x2F;code&gt; in our runner. AWS provides &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;awslabs&#x2F;amazon-ecr-credential-helper&quot;&gt;amazon-ecr-credential-helper&lt;&#x2F;a&gt; which is a neat way of automatically authenticating with AWS ECR based on your Access Keys&#x2F;IAM role. What does automatic mean here? So, the normal &lt;code&gt;docker login&lt;&#x2F;code&gt; is a basic auth command, where if you’ve to log in to ECR, you need to do something like:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ecr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get-login-password&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-region&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; region&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; login&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-username&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; AWS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-password-stdin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; aws_account_id.dkr.ecr.region.amazonaws.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is problematic because the authorization token is valid for 12 hours. Further, you’ve to log in to multiple registry IDs separately. Managing this is a nightmare, so Docker instead of just relying on Basic Auth, came up with a neat mechanism: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;docker&#x2F;docker-credential-helpers&quot;&gt;docker-credential-helpers&lt;&#x2F;a&gt;. This allows you to keep your secret tokens in your Keystore. A new credential helper can be written in &lt;code&gt;Go&lt;&#x2F;code&gt; which implements the &lt;code&gt;credentials.Helper&lt;&#x2F;code&gt; interface. This is what &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;awslabs&#x2F;amazon-ecr-credential-helper&quot;&gt;amazon-ecr-credential-helper&lt;&#x2F;a&gt; does by offering various ways like AWS IAM Roles, Assumed Roles, Access Keys, etc to authenticate with ECR.&lt;&#x2F;p&gt;
&lt;p&gt;This is where I stumbled the most. I downloaded the binary from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;awslabs&#x2F;amazon-ecr-credential-helper&#x2F;releases&#x2F;tag&#x2F;v0.4.0&quot;&gt;Github Releases&lt;&#x2F;a&gt; but this binary is statically compiled with &lt;code&gt;muslc&lt;&#x2F;code&gt; libraries.&lt;&#x2F;p&gt;
&lt;p&gt;However &lt;code&gt;gitlab&#x2F;gitlab-runner&lt;&#x2F;code&gt; is based on the &lt;code&gt;ubuntu&lt;&#x2F;code&gt; docker image, so the above binary never worked. The strangest thing was the unhelpful error message that &lt;code&gt;sh&lt;&#x2F;code&gt; returned as explained in this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forum.gitlab.com&#x2F;t&#x2F;bin-sh-eval-line-97-mybinary-not-found&#x2F;27125&#x2F;3&quot;&gt;post&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To make things easier, I baked my own &lt;code&gt;gitlab-runner&lt;&#x2F;code&gt; image with the above binary compiled inside the image
using &lt;code&gt;go get&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; ubuntu:20.04 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;ENV&lt;&#x2F;span&gt;&lt;span&gt; DEBIAN_FRONTEND=noninteractive &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; : \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;amp;&amp;amp; apt-get update \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;amp;&amp;amp; apt-get install --no-install-recommends -y git golang-go ca-certificates \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;amp;&amp;amp; rm -rf &#x2F;var&#x2F;lib&#x2F;apt&#x2F;lists&#x2F;* \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; go get -u github.com&#x2F;awslabs&#x2F;amazon-ecr-credential-helper&#x2F;ecr-login&#x2F;cli&#x2F;docker-credential-ecr-login&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; mv &#x2F;root&#x2F;go&#x2F;bin&#x2F;docker-credential-ecr-login .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; gitlab&#x2F;gitlab-runner:v13.8.0 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=build &#x2F;build&#x2F;docker-credential-ecr-login &#x2F;usr&#x2F;local&#x2F;bin&#x2F;docker-credential-ecr-login&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above image bakes in the &lt;code&gt;docker-credential-ecr-login&lt;&#x2F;code&gt; binary and also puts it under &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;code&gt; so it’ll be available under &lt;code&gt;$PATH&lt;&#x2F;code&gt; to the Docker engine.&lt;&#x2F;p&gt;
&lt;p&gt;With the above 2 things, if the runner’s server (EC2 instance&#x2F;K8s pod) has access to the ECR image, it should be able to pull.&lt;&#x2F;p&gt;
&lt;p&gt;Now coming to the 2nd problem, where we wanted &lt;code&gt;kaniko&lt;&#x2F;code&gt; to authenticate to ECR, things are a bit simpler:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Kaniko comes with &lt;code&gt;docker-credential-ecr-login&lt;&#x2F;code&gt; baked in. All you need to do is add the following to &lt;code&gt;~&#x2F;.docker&#x2F;config.json&lt;&#x2F;code&gt; as explained &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GoogleContainerTools&#x2F;kaniko&#x2F;blob&#x2F;master&#x2F;README.md#pushing-to-amazon-ecr&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{ &amp;quot;credsStore&amp;quot;: &amp;quot;ecr-login&amp;quot; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we need to mount the AWS Credentials to Kaniko’s image so that it can use AWS SDK to perform a login to ECR. We do that by using &lt;code&gt;volumes&lt;&#x2F;code&gt; of the &lt;code&gt;runner&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[runners.docker]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;volumes = [&amp;quot;&#x2F;home&#x2F;ubuntu&#x2F;runners&#x2F;test&#x2F;aws-credentials:&#x2F;root&#x2F;.aws&#x2F;credentials:ro&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This mounts the &lt;code&gt;aws-credentials&lt;&#x2F;code&gt; file from the host inside the container which the runner spawned (&lt;code&gt;kaniko&lt;&#x2F;code&gt; in this case).&lt;&#x2F;p&gt;
&lt;p&gt;A sample &lt;code&gt;aws-credentials&lt;&#x2F;code&gt; file if you’re using a cross-account access can look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[default]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;role_arn=arn:aws:iam::ACCOUNT_ID:role&#x2F;assume-role-{{ROLE_NAME}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;credential_source=Ec2InstanceMetadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;region=ap-south-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can put in your normal AWS Keys or leave them blank if you want to use your IAM Role. With mounting the AWS Credentials inside Kaniko’s container, you can authenticate to cross-account ECRs as well (once you set up the whole assumed-role&#x2F;trusted entities flow).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sample-runner&quot;&gt;Sample Runner&lt;a class=&quot;zola-anchor&quot; href=&quot;#sample-runner&quot; aria-label=&quot;Anchor link for: sample-runner&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you want to take a look at how the complete flow looks like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Start the Runner service using &lt;code&gt;docker-compose&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3.7&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;est&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; As explained above, this image has `docker-credentials-ecr-login` baked in.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;CCOUNT_ID&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dkr.ecr.ap-south-1.amazonaws.com&#x2F;custom&#x2F;gitlab-runner:13.8.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;estart&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lways&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Automatically created; config.toml.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&#x2F;test&#x2F;runner-config:&#x2F;etc&#x2F;gitlab-runner&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Mount AWS Credentials for Docker Executor to authenticate.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&#x2F;test&#x2F;aws-credentials:&#x2F;root&#x2F;.aws&#x2F;credentials:ro&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Mount Docker Socket so that executor can communicate with it.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;var&#x2F;run&#x2F;docker.sock:&#x2F;var&#x2F;run&#x2F;docker.sock&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Register a new runner:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;docker-compose exec test register&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fill in the basic info and edit &lt;code&gt;.&#x2F;test&#x2F;runner-config.toml&lt;&#x2F;code&gt; with the following options:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[runners]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name = &amp;quot;Test&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  executor = &amp;quot;docker&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  environment = [&amp;quot;DOCKER_AUTH_CONFIG={ \&amp;quot;credsStore\&amp;quot;: \&amp;quot;ecr-login\&amp;quot; }&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [runners.docker]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    volumes = [&amp;quot;&#x2F;home&#x2F;ubuntu&#x2F;runners&#x2F;test&#x2F;aws-credentials:&#x2F;root&#x2F;.aws&#x2F;credentials:ro&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Honestly, this was a lot of trial and error to figure out how to use private images with Gitlab. Some important links and references that helped me figure this out:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;bmares&#x2F;gitlab-runner-ecr-auth-example&#x2F;&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;bmares&#x2F;gitlab-runner-ecr-auth-example&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-runner&#x2F;-&#x2F;issues&#x2F;1583#note_84649153&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-runner&#x2F;-&#x2F;issues&#x2F;1583#note_84649153&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Designing a simple Job Queue in Golang</title>
        <published>2020-12-01T08:10:55+05:30</published>
        <updated>2020-12-01T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/job-queue-golang/"/>
        <id>https://mrkaran.dev/posts/job-queue-golang/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/job-queue-golang/">&lt;p&gt;In this post we’ll see how to create a simple job queue in Golang. There are tonnes of libraries and posts out there doing overly complicated stuff, however if your need is pretty minimal or you want to understand the concepts from ground up, this post aims to do just that and nothing more.&lt;&#x2F;p&gt;
&lt;p&gt;We’ll be using concepts like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;sync&#x2F;#WaitGroup&quot;&gt;WaitGroup&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;doc&#x2F;effective_go.html#concurrency&quot;&gt;Channels&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;context&#x2F;&quot;&gt;Contexts&lt;&#x2F;a&gt; to build our own Job Queuing mechanism. It primarily involves 2 components:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Queue&lt;&#x2F;strong&gt;: A queue which has a list of items waiting to be processed.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Worker&lt;&#x2F;strong&gt;: A &lt;em&gt;worker&lt;&#x2F;em&gt; constantly listening to that queue and &lt;em&gt;processing&lt;&#x2F;em&gt; the events as desired.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With these 2 main ideas behind us, let us create our sample structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;package&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; dispatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Dispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; interface&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Push takes an Event and pushes to a queue.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;	Push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Run spawns the workers and waits indefinitely for&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; the events to be processed.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;	Run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; EventDispatcher represents the datastructure for an&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; EventDispatcher instance. This struct satisfies the&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Dispatcher interface.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; EventDispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Opts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;     Options&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Queue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; models&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Finished&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Options represent options for EventDispatcher.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Options&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MaxWorkers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Number of workers to spawn.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MaxQueueSize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Maximum length for the queue to hold events.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; NewEventDispatcher initialises a new event dispatcher.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; NewEventDispatcher&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;opts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Options&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Dispatcher&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; EventDispatcher&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Opts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Queue&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;MaxQueueSize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Finished&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;pushing-to-queue&quot;&gt;Pushing to Queue&lt;a class=&quot;zola-anchor&quot; href=&quot;#pushing-to-queue&quot; aria-label=&quot;Anchor link for: pushing-to-queue&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we have our basic structure ready, let’s write a function to push events to queue.&lt;&#x2F;p&gt;
&lt;p&gt;A queue is simply a channel. We have created a new queue of size &lt;code&gt;MaxQueueSize&lt;&#x2F;code&gt; while initialising the &lt;code&gt;EventDispatcher&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Queue: make(chan Event, opts.MaxQueueSize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To push events into it, we’ll simply do: &lt;code&gt;d.Queue &amp;lt;- event&lt;&#x2F;code&gt;. This adds a new item (&lt;code&gt;event&lt;&#x2F;code&gt;) of type &lt;code&gt;Event&lt;&#x2F;code&gt; to our queue.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Push adds a new event payload to the queue.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;d &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;EventDispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;event&lt;&#x2F;span&gt;&lt;span&gt; Event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Finished&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span&gt; errors&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;New&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;queue is closed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Queue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;listening-to-queue&quot;&gt;Listening to Queue&lt;a class=&quot;zola-anchor&quot; href=&quot;#listening-to-queue&quot; aria-label=&quot;Anchor link for: listening-to-queue&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;So the client is calling &lt;code&gt;Push()&lt;&#x2F;code&gt; on our &lt;code&gt;EventDispatcher&lt;&#x2F;code&gt; and events are being pushed in the channel. But there’s no one reading from this channel so far. Let’s fix that by spawning workers, who will listen on the channel &lt;em&gt;indefinitely&lt;&#x2F;em&gt; and process the events:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        case&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Queue&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        event&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Process&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the above snippet, we are simply looping indefinitely to scan through all items in the queue. &lt;code&gt;event &amp;lt;- d.Queue&lt;&#x2F;code&gt; is basically fetching the item from the channel and assigning a value to it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;event.Process()&lt;&#x2F;code&gt; is a dummy function but it basically indicates that whatever processing that needs to be done should be handled here.&lt;&#x2F;p&gt;
&lt;p&gt;Right now, you’ll be wondering two things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If this is an infinite loop, how do we guarantee it runs forever?&lt;&#x2F;li&gt;
&lt;li&gt;How do I spawn more workers if I need concurrency?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To address these problems, let’s add in WaitGroups and GoRoutines to our mix.&lt;&#x2F;p&gt;
&lt;p&gt;WaitGroups will help us keep a count of workers which have been spawned and until each one of them finishes processing, wait groups will keep blocking indefinitely using &lt;code&gt;wg.Wait()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And to bring in more workers, we’ll simply spawn them with GoRoutines:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	  select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	    case&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Queue&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		event&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Process&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, spawning &lt;code&gt;n&lt;&#x2F;code&gt; Goroutines is just a matter of a simple for loop over this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Opts&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;MaxWorkers&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add a wait group for each worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			case&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Queue&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			event&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Process&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! But hang on! We have missed a critical thing. How do we handle cancellations? For eg, when your program shuts down, we should clean up all the Goroutines spawned and process the remaining messages in queue. For that, we need to listen to a &lt;code&gt;Cancellation&lt;&#x2F;code&gt; channel. The only purpose of this channel is to listen for SIGINT or SIGTERM signals and whenever either of them is received, we should flush our events.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s how the client would initialise a context:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Create a channel to relay `SIGINT` and `SIGTERM` signals.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;closeChan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Signal&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;signal&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Notify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;closeChan&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Interrupt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; syscall&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;SIGTERM&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ctx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; cancel&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;WithCancel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Background&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And in the main thread, the client would block on &lt;code&gt;closeChan&lt;&#x2F;code&gt; channel like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Listen on close channel indefinitely until a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; `SIGINT` or `SIGTERM` is received.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt;closeChan&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Cancel the context to gracefully shutdown.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;cancel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When &lt;code&gt;cancel()&lt;&#x2F;code&gt; is called, it does something special. It passes a value to &lt;code&gt;ctx.Done()&lt;&#x2F;code&gt; channel. We can listen to this channel in the &lt;code&gt;.Run()&lt;&#x2F;code&gt; function and flush pending events accordingly:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; ctx&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Ensure no new messages are added.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Finished&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Flush all events.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	e&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Flush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; This Goroutine has finished processing.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Stitching all pieces together, we finally have:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;package&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; dispatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Dispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; interface&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Push takes an Event and pushes to a queue.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;	Push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Run spawns the workers and waits indefinitely for&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; the events to be processed.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;	Run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; EventDispatcher represents the datastructure for an&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; EventDispatcher instance. This struct satisfies the&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Dispatcher interface.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; EventDispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Opts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;     Options&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Queue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; models&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Finished&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Options represent options for EventDispatcher.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Options&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MaxWorkers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Number of workers to spawn.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	MaxQueueSize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Maximum length for the queue to hold events.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; NewEventDispatcher initialises a new event dispatcher.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; NewEventDispatcher&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;opts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Options&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Dispatcher&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; EventDispatcher&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Opts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Queue&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;MaxQueueSize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Finished&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Push adds a new event payload to the queue.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;d &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;EventDispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;event&lt;&#x2F;span&gt;&lt;span&gt; Event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Finished&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span&gt; errors&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;New&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;queue is closed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Queue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Run spawns workers and listens to the queue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; It&amp;#39;s a blocking function and waits for a cancellation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; invocation from the Client.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;d &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;EventDispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;ctx&lt;&#x2F;span&gt;&lt;span&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	wg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Opts&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;MaxWorkers&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add a wait group for each worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Spawn a worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;			for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				case&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt;ctx&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;					&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Ensure no new messages are added.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;					d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Finished&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;					&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Flush all events&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;					e&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Flush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;					wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;					return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;				case&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Queue&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;					e&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Process&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;Wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Push adds a new event payload to the queue.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;d &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;EventDispatcher&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; Push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;event&lt;&#x2F;span&gt;&lt;span&gt; Event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Finished&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span&gt; errors&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt;New&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;queue is closed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	d&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Queue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This post doesn’t cover how to flush or process the events as these are implementation specific details.
This is a pretty barebones structure and you can modify the code according to your usecase.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Analysis Paralysis - CrashLoopBackoff</title>
        <published>2020-11-27T08:10:55+05:30</published>
        <updated>2020-11-27T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/analysis-paralysis/"/>
        <id>https://mrkaran.dev/posts/analysis-paralysis/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/analysis-paralysis/">&lt;p&gt;Have you ever been stuck in a situation where you’ve spent countless hours digging through lot of options, overthinking their pros&#x2F;cons and having a tough time to decide?&lt;&#x2F;p&gt;
&lt;p&gt;If yes, I’ve been in the same boat myself and the more I think about this, I think it’s causing some serious issues in my productivity. Since I’ve started to self host a lot of services, I’m overthinking and overanalysing the software choices available to do a certain task. For eg, a personal wiki, sounds such a simple and common use case but I’ve personally tried countless choices. I’ve read and searched for these discussions on lobster&#x2F;HN&#x2F;Reddit discussions boards and that has been a real time sink for me, now that I look back. I’ll try an option for maybe a week or two at best and then jump on to something else in search of &lt;em&gt;the perfect&lt;&#x2F;em&gt; solution.&lt;&#x2F;p&gt;
&lt;p&gt;It’s hard for me to stick to a solution. And it’s even more embarassing when you tell your friends about the “latest new distro” you’re using, announce it to the world on Twitter and when someone asks, “hey how’s that OS working for you” after a month, you tell them “Oh, I switched from it last week”. I’m not making any of this up, I’ve been in these shoes myself and honestly it’s not a good feeling.&lt;&#x2F;p&gt;
&lt;p&gt;In the search of &lt;em&gt;perfect&lt;&#x2F;em&gt; I tend to lose sight of things that are important. Things which are slow, boring but they &lt;em&gt;work&lt;&#x2F;em&gt; are more reliable than a software which changes fast and breaks often. I want to fail cheap and quickly rather than spending a lot of time and still eventually failing.&lt;&#x2F;p&gt;
&lt;p&gt;No, this post doesn’t have any answers on how to fix this problem. Well, if I myself knew then I’d not be writing this but giving a TEDx talk on it. These are just my observations and something that I intend to actively fix.&lt;&#x2F;p&gt;
&lt;p&gt;Boring is better. I want to stick to stable choices when it comes to trivial things in life. I don’t wanna seek excitement or joy from switching to a cool new distro. Instead, by actually doing some important project at my work or building my side projects, something that gives me a genuine feeling of happiness. After all grass always seems to look greener on the other side.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t usually pen down my thoughts like these, but I want to refer to this public post as a reminder for myself the next time I’m about to make the same mistake.&lt;&#x2F;p&gt;
&lt;p&gt;Fin.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;&#x2F;strong&gt; (2021-11-02): There’s a really nice &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=VO6XEQIsCoM&amp;amp;t=638&quot;&gt;video&lt;&#x2F;a&gt; I came across today on the same subject. I’d highly recommend you to give this a listen if you found the above post relatable.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Migrating my blog to Zola</title>
        <published>2020-11-08T08:10:55+05:30</published>
        <updated>2020-11-08T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/migrating-to-zola/"/>
        <id>https://mrkaran.dev/posts/migrating-to-zola/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/migrating-to-zola/">&lt;p&gt;I’ve been writing on this blog for about 2 years now. This has been the longest I’ve stuck on to the same &lt;em&gt;technology stack&lt;&#x2F;em&gt; for my blog. I’ve previously jumped from a Jekyll based static site to a Medium blog before finally settling for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;Hugo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been using Hugo since 2018 but I don’t recall as to &lt;em&gt;why&lt;&#x2F;em&gt; I went ahead with it. Maybe it was increasingly popular at that time and everyone touted Hugo as &lt;em&gt;the&lt;&#x2F;em&gt; solution to Static Site Generator (referred to as SSG from here on). There are 1000s of SSGs and at least a dozen of websites which lists all the SSGs out there. This is crazy by any standards. Hugo started as a generic blog generator but over the years it has become a &lt;em&gt;website generator&lt;&#x2F;em&gt;. It’s no longer aimed at people who just want to have a small little static website&#x2F;blog but supports all the use cases for people building full-fledged static websites. IMHO these two goals are overarching however this has resulted in a simple project to become incredibly complex over time.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tipping-point&quot;&gt;Tipping Point&lt;a class=&quot;zola-anchor&quot; href=&quot;#tipping-point&quot; aria-label=&quot;Anchor link for: tipping-point&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Anyway, so I wanted to change the look of the homepage on my website so I decided to look at Hugo’s documentation. Hugo’s documentation is great for someone who knows what exactly are they looking for. The documentation is so huge that you simply cannot grok it in one evening. I had zero ideas on how to customise the damn homepage of my blog and after spending hours buried in the documentation I was able to kind of figure the solution but it was unintuitive, to say the least. Apparently, to override any template from the theme, you have to mirror the directory structure of the theme in your root directory. Which meant, I needed to look at the source code of the theme, figure out the project structure, copy-paste all the folder names and put my override of &lt;code&gt;index.html&lt;&#x2F;code&gt; there. Which, BTW &lt;strong&gt;magically&lt;&#x2F;strong&gt; overrides it. This whole magic thing is BS and I am being strongly opinionated here.&lt;&#x2F;p&gt;
&lt;p&gt;There is more than one way to do something in Hugo. Different theme authors use different styles, which makes the whole thing even more complex. It also means for my customisations to work across themes, well you guessed it right: &lt;strong&gt;it’s impossible&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Recently I discovered that I was unable to preview my Hugo website locally without internet because I had a Twitter &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;content-management&#x2F;shortcodes&#x2F;#tweet&quot;&gt;shortcode&lt;&#x2F;a&gt; in one of my blog post (which makes an API call to Twitter to render a nice card preview). The site completely failed to render instead of just logging a warning. Bollocks.&lt;&#x2F;p&gt;
&lt;p&gt;The tipping point for me, however, was when the theme I was using stopped working with the latest version of Hugo at that point. So, picture this – You make dozens of custom changes and then one update just &lt;em&gt;breaks&lt;&#x2F;em&gt; your website. Now not only you have to fix your shit but the theme you were using, you’ve to make upstream changes to the theme or maintain your own fork. And no, this is not a one-off experience. Hugo upgrades are a joke, they are known to break very very often.&lt;&#x2F;p&gt;
&lt;p&gt;I was done at this point. I didn’t want to deal with this BS of continuously fighting the generator for my blog.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-fresh-change&quot;&gt;A fresh change&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-fresh-change&quot; aria-label=&quot;Anchor link for: a-fresh-change&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Being a practitioner of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;projects.csail.mit.edu&#x2F;gsb&#x2F;old-archive&#x2F;gsb-archive&#x2F;gsb2000-02-11.html&quot;&gt;Yak Shaving&lt;&#x2F;a&gt;, I discussed the idea of a “tinyhugo” with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nadh.in&#x2F;&quot;&gt;Kailash&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.saratchandra.in&#x2F;&quot;&gt;Sarat&lt;&#x2F;a&gt;. We’d arrived at a spec and I started writing some code to pander to my NIH syndrome.&lt;&#x2F;p&gt;
&lt;p&gt;However, I was still not convinced that a simpler solution doesn’t exist. I spent countless hours exploring other alternatives. I’d used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getlektor.com&#x2F;&quot;&gt;Lektor&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.getpelican.com&#x2F;&quot;&gt;Pelican&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.11ty.dev&#x2F;&quot;&gt;Eleventy&lt;&#x2F;a&gt; before finally stumbling upon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; from HN&#x2F;Lobster discussions. I’ve got to say, the landing page gave a &lt;em&gt;fresh&lt;&#x2F;em&gt; feeling - one that I’ve not seen with any other alternatives. In fact quite opposite to the Eleventy landing page which looks like an over-engineered piece of software to generate websites (Not hating on it, there might be use cases for it, but the JS tooling and dependency system is something that I would not want to touch with a 10ft pole).&lt;&#x2F;p&gt;
&lt;p&gt;Zola’s primary appeal to me was that like Hugo it’s extremely fast and comes as a single binary no dependency package. I looked at the docs the first impression was they are concise enough to get a basic idea. Zola is strongly opinionated, even to the extent of dictating a project structure and sometimes filenames too. I actually preferred this over the &lt;em&gt;magic&lt;&#x2F;em&gt; Hugo does. In less than 2 hours I was able to port the home page of my blog (and tweak it to my liking) in Zola. I decided to abandon my own &lt;code&gt;tinyhugo&lt;&#x2F;code&gt; attempt because for the very fact Zola fits my needs very well.&lt;&#x2F;p&gt;
&lt;p&gt;The thing that I really loved about Zola is how it enforces a separation between &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;content&#x2F;section&#x2F;&quot;&gt;Section&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;content&#x2F;page&#x2F;&quot;&gt;Pages&lt;&#x2F;a&gt;. The section represents a “collection” of posts. So a &lt;em&gt;blog&lt;&#x2F;em&gt; can be a section, and I can have another section called “Book Reviews”. I could easily tell Zola where to look for the templates by specifying the same in &lt;code&gt;content&#x2F;book_reviews&#x2F;_index.md&lt;&#x2F;code&gt;. I don’t have to read Hugo docs or do &lt;em&gt;Google-fu&lt;&#x2F;em&gt; to figure this out, it’s right there in the docs and very apparent.&lt;&#x2F;p&gt;
&lt;p&gt;For the record, I still don’t know how to customise different templates for different sections in Hugo, but I couldn’t care less.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;migration&quot;&gt;Migration&lt;a class=&quot;zola-anchor&quot; href=&quot;#migration&quot; aria-label=&quot;Anchor link for: migration&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The migration was pretty straightforward – I had to copy the &lt;code&gt;content folder&lt;&#x2F;code&gt;s of my blog (which are just a bunch of &lt;code&gt;.md&lt;&#x2F;code&gt; files) and replace &lt;code&gt;YAML&lt;&#x2F;code&gt; frontmatter to &lt;code&gt;TOML&lt;&#x2F;code&gt;. There were a few variable changes that I needed to do manually but since they were a manageable 20-25 posts, I did it by hand. I could potentially automate but then rabbit deep in the rabbit hole of Yak Shaving. The good part was that I was able to retain the same URL structure for my new blog because the URL scheme was based on the file paths.&lt;&#x2F;p&gt;
&lt;p&gt;I spent some time porting &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;knadh&#x2F;hugo-ink&quot;&gt;hugo-ink&lt;&#x2F;a&gt; to Zola and did minor CSS tweaks to it. Zola uses the Tera language for templating and it’s much more pleasing to eyes than the Go Template syntax. Zola comes with pretty neat features like Search, RSS&#x2F;Atom Feeds, Syntax Highlighting and SASS-&amp;gt;CSS Processors.&lt;&#x2F;p&gt;
&lt;p&gt;What took me time however was to figure out how to get &lt;code&gt;opengraph&lt;&#x2F;code&gt; tags in each page. Hugo provides nifty &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gohugoio&#x2F;hugo&#x2F;blob&#x2F;master&#x2F;tpl&#x2F;tplimpl&#x2F;embedded&#x2F;templates&#x2F;opengraph.html&quot;&gt;template&lt;&#x2F;a&gt; for this use case but Zola is pretty barebones like that. People who care a lot about SEO need to spend some extra efforts here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;future&quot;&gt;Future&lt;a class=&quot;zola-anchor&quot; href=&quot;#future&quot; aria-label=&quot;Anchor link for: future&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Zola is still a pretty new kid on the block but the author shares the same frustration about Hugo:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;it personally drives me insane, to the point of writing my own template engine and static site generator. Yes, this is a bit biased. – &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola#-explanations&quot;&gt;Source&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This also reflects in the issues&#x2F;PRs I’ve seen for Zola and the author is opinionated about not adding features which would make Zola complicated. Overall I am very happy with the switch and it was long due. I feel more confident in tweaking certain sections of my website. I plan to open-source the current theme in the next few days.&lt;&#x2F;p&gt;
&lt;p&gt;You can read the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.mrkaran.dev&#x2F;karan&#x2F;website&quot;&gt;Source Code&lt;&#x2F;a&gt; of this website if you’d like to explore how this website is built.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Import existing Route53 records in Terraform</title>
        <published>2020-10-18T08:10:55+05:30</published>
        <updated>2020-10-18T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/terraform-route53-import/"/>
        <id>https://mrkaran.dev/posts/terraform-route53-import/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/terraform-route53-import/">&lt;p&gt;Terraform has a straightforward way of importing existing records (managed outside Terraform) via &lt;code&gt;terraform import&lt;&#x2F;code&gt; command. The usage is documented &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;providers&#x2F;hashicorp&#x2F;aws&#x2F;latest&#x2F;docs&#x2F;resources&#x2F;route53_record&quot;&gt;here&lt;&#x2F;a&gt; and works well if you have a handful of records to import. However when you work with custom Terraform modules &lt;em&gt;and&lt;&#x2F;em&gt; have a whole bunch of records to be imported, you’d look out ways to &lt;strong&gt;script&lt;&#x2F;strong&gt; the entire workflow. I did this a few weeks back at work and thought to share a solution which works well for my usecase.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-it-works&quot;&gt;How it works&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-it-works&quot; aria-label=&quot;Anchor link for: how-it-works&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The task consists of 3 parts:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-import-all-existing-records-in-a-hosted-zone-using-aws-cli&quot;&gt;1. Import all existing records in a hosted zone using &lt;code&gt;AWS CLI&lt;&#x2F;code&gt;.&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-import-all-existing-records-in-a-hosted-zone-using-aws-cli&quot; aria-label=&quot;Anchor link for: 1-import-all-existing-records-in-a-hosted-zone-using-aws-cli&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; route53&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; list-resource-record-sets&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-hosted-zone-id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; XXX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; data&#x2F;company-tld.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Loads the zone records in a dict&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; load_records&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;zone_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ZONE_FILE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;zone_file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; record_file&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; json&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;record_file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;2-import-the-record-in-terraform-state&quot;&gt;2. Import the record in Terraform state.&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-import-the-record-in-terraform-state&quot; aria-label=&quot;Anchor link for: 2-import-the-record-in-terraform-state&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;To do this, Terraform CLI comes with an &lt;code&gt;import&lt;&#x2F;code&gt; command. However for &lt;code&gt;import&lt;&#x2F;code&gt; to work, you need to have a resource declaration in your Terraform file already.&lt;&#x2F;p&gt;
&lt;p&gt;From the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.terraform.io&#x2F;docs&#x2F;import&#x2F;index.html#currently-state-only&quot;&gt;official documentation&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Because of this, prior to running terraform import it is necessary to write manually a resource configuration block for the resource, to which the imported object will be mapped.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To overcome this restriction, we will create a &lt;code&gt;dummy.tf&lt;&#x2F;code&gt; and programatically write the configuration block for each record.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Writes the dummy Terraform template which is required&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; before `terraform import` runs.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; template_dummy_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    add_dummy_record&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Template&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	resource &amp;quot;aws_route53_record&amp;quot; &amp;quot;$resource_name&amp;quot; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	# (resource arguments)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dummy_file_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;TERRAFORM_DIR&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dummy.tf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;dummy_file_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        f&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;add_dummy_record&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;substitute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;AWS Route53 module can import &lt;code&gt;aws_route53_record&lt;&#x2F;code&gt; as decsribed &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;providers&#x2F;hashicorp&#x2F;aws&#x2F;latest&#x2F;docs&#x2F;resources&#x2F;route53_record#import&quot;&gt;here&lt;&#x2F;a&gt;. We will run this command as a subprocess.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Shells out `terraform import` command in the host OS.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; terraform_import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resource_type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    import_command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;terraform import aws_route53_record.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ZONE_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;import_command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; check&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;3-optional-move-resources-in-a-module&quot;&gt;3. (Optional) Move Resources in a Module&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-optional-move-resources-in-a-module&quot; aria-label=&quot;Anchor link for: 3-optional-move-resources-in-a-module&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In case you are using a Module to manage AWS Route53 resources, you’ll need to move the declaration from &lt;code&gt;resource&lt;&#x2F;code&gt; to &lt;code&gt;module&lt;&#x2F;code&gt; configuration block. This is described more in detail &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.terraform.io&#x2F;docs&#x2F;commands&#x2F;state&#x2F;mv.html#example-move-a-resource-into-a-module&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The module declaration&#x2F;naming would depend on how the module is configured. To demonstrate, the module I use internally requires the name to be of the format &lt;code&gt;resource_name-resource_type&lt;&#x2F;code&gt;. To achieve this, you can call &lt;code&gt;terraform state mv&lt;&#x2F;code&gt; as a subprocess:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Shells out `terraform state mv` command in the host OS.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; terraform_move&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resource_type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mv_command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;terraform state mv aws_route53_record.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;module.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;MODULE_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.aws_route53_record.route53_record[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mv_command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; check&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s it! Running &lt;code&gt;terraform plan&lt;&#x2F;code&gt; should now show you the changes and if you imported every record correctly you should not see any &lt;em&gt;drift&lt;&#x2F;em&gt; from the real world state.&lt;&#x2F;p&gt;
&lt;p&gt;You can view the entire script here:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; getenv&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; subprocess&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; sys&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; import&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; exit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ZONE_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ZONE_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;MODULE_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;MODULE_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ZONE_FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ZONE_FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;TERRAFORM_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; getenv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;TERRAFORM_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Returns the variable key if not present in ENV.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; check_env_vars&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; ZONE_FILE&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$ZONE_FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; ZONE_ID&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$ZONE_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; MODULE_NAME&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$MODULE_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; TERRAFORM_DIR&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$TERRAFORM_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Loads the zone records in a dict&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; load_records&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;zone_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ZONE_FILE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;zone_file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; record_file&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; json&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;record_file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Writes the dummy Terraform template which is required&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; before `terraform import` runs.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; template_dummy_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    add_dummy_record&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Template&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	resource &amp;quot;aws_route53_record&amp;quot; &amp;quot;$resource_name&amp;quot; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	# (resource arguments)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dummy_file_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;TERRAFORM_DIR&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dummy.tf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    with&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;dummy_file_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        f&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;add_dummy_record&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;substitute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Shells out `terraform import` command in the host OS.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; terraform_import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resource_type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    import_command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;terraform import aws_route53_record.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ZONE_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;import_command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; check&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Shells out `terraform state mv` command in the host OS.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; terraform_move&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resource_type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mv_command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;terraform state mv aws_route53_record.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;module.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;MODULE_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.aws_route53_record.route53_record[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mv_command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#E36209, #F69D50);&quot;&gt; check&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    missing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; check_env_vars&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; missing&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Required env variable &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;missing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; is missing.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    records&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; load_records&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; records&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ResourceRecordSets&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        resource_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        template_dummy_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        terraform_import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resource_type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        terraform_move&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resource_type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Imported &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;resource_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hope this tiny Python script helps you transition your AWS Route53 records neatly and effortlessly!&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Setting up a RIPE Atlas Probe</title>
        <published>2020-10-03T08:10:55+05:30</published>
        <updated>2020-10-03T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/ripe-atlas-probe-setup/"/>
        <id>https://mrkaran.dev/posts/ripe-atlas-probe-setup/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/ripe-atlas-probe-setup/">&lt;p&gt;Twitter is an amazing thing! For all the shitposting and meme-ing that’s done there, there are some really cool people you get to interact with which wouldn’t have been possible IRL. I happened to stumble upon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;pswapneel&quot;&gt;Swapneel&lt;&#x2F;a&gt; last year in Bangalore at a meetup. He occasionally posts about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;&quot;&gt;RIPE Atlas&lt;&#x2F;a&gt; Probes measurements on his Twitter feed and that made me curious and learn more about the Atlas Probe. Call it the Baader-Meinhof effect but just when I was reading his &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;brainattic.in&#x2F;blog&#x2F;2020&#x2F;03&#x2F;27&#x2F;host-a-ripe-atlas-software-probe-in-your-network&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; on RIPE Atlas, I found about a Hasgeek &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hasgeek.com&#x2F;rootconf&#x2F;measuring-the-internet-using-ripe-atlas&#x2F;&quot;&gt;workshop&lt;&#x2F;a&gt; which is being conducted by Swapneel himself and well, that’s how I basically got interested in setting up a probe myself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-ripe-atlas-probe&quot;&gt;What is RIPE Atlas Probe&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-ripe-atlas-probe&quot; aria-label=&quot;Anchor link for: what-is-ripe-atlas-probe&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;about&#x2F;probes&#x2F;&quot;&gt;Probe&lt;&#x2F;a&gt; is a device used to measure various metrics like DNS, SSL&#x2F;TLS, NTP, ping, traceroute etc for an upstream target. A network of such probes is useful not just to internet researchers, network engineers, ISP operators, public activists but also to common folks like me who are simply curious about the network&#x2F;WWW in general. The idea behind this is simple – you get some virtual credits for hosting a probe. You can make use of these credits to run your own measurements to gain insights about the health of your network. The data from these measurements are made publicly available by RIPE NCC and anyone can see these results.&lt;&#x2F;p&gt;
&lt;p&gt;There are 2 ways to host a Probe: &lt;strong&gt;Software&lt;&#x2F;strong&gt; and &lt;strong&gt;Hardware&lt;&#x2F;strong&gt;. Since the start of this year, RIPE Atlas is available as software packages for various platforms. Before this, the only way to set up a Probe was to host a Hardware probe by applying for one at RIPE NCC website. These hardware probes are not shipping to India since quite some time as Swapneel mentioned and if you’re in India, your only choice, for now, is to set up a software probe. A few key differences in the 2 kinds of probes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Initial Setup&lt;&#x2F;strong&gt;: Hardware probe is a plug-n-play device, no setup required. That makes it attractive for a lot of people, to just get a small device and host it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Spare Compute&lt;&#x2F;strong&gt;: For hosting a probe it is recommended that the probe stays online for as long as possible. This means you need to have a spare compute lying around, like a RaspebrryPi, a VM, a server etc. It’s not really recommended to host a probe on your laptop&#x2F;desktop - something which has ad-hoc usage pattern. For people who don’t have any spare compute, a hardware probe is more suited for them.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tampering Result&lt;&#x2F;strong&gt;: With the software probe, there are easy ways of tampering the measurement result, which might give a bad data point to people running the measurements. For eg, a software probe could tamper with the DNS queries for a particular upstream and fool you to believe that there’s a problem with the uplink or the upstream target.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can read more about Probes &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;about&#x2F;probes&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;about&#x2F;faq&#x2F;&quot;&gt;FAQ&lt;&#x2F;a&gt; section is highly recommended to clear all the basic doubts you might have about Probes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-up-a-software-probe-in-a-container&quot;&gt;Setting up a Software Probe in a Container&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-a-software-probe-in-a-container&quot; aria-label=&quot;Anchor link for: setting-up-a-software-probe-in-a-container&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Well, Containers &lt;em&gt;are&lt;&#x2F;em&gt; awesome! It’s easier to do a &lt;code&gt;docker run&lt;&#x2F;code&gt; than figure out the installation instructions for your OS, ensure dependencies are installed and &lt;em&gt;insert 10 other things you have to do&lt;&#x2F;em&gt;. So, I decided to use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Jamesits&#x2F;docker-ripe-atlas&quot;&gt;jamesits&#x2F;ripe-atlas&lt;&#x2F;a&gt; Docker image to host a probe on my RPi 4.&lt;&#x2F;p&gt;
&lt;p&gt;However, in case you don’t want to use Containers for a reason best known to you, you can visit the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;docs&#x2F;software-probe&#x2F;&quot;&gt;official docs&lt;&#x2F;a&gt; and find out instructions for your platform.&lt;&#x2F;p&gt;
&lt;p&gt;You can follow the below steps to set up a probe via Docker:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-create-a-ripe-ncc-account&quot;&gt;1. Create a RIPE NCC Account&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-create-a-ripe-ncc-account&quot; aria-label=&quot;Anchor link for: 1-create-a-ripe-ncc-account&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;You need to register for a RIPE NCC Access Account before proceeding further. Visit the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;access.ripe.net&#x2F;registration&quot;&gt;registration&lt;&#x2F;a&gt; page and create an account.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-start-the-container&quot;&gt;2. Start the container&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-start-the-container&quot; aria-label=&quot;Anchor link for: 2-start-the-container&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-detach&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-restart=always&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-log-opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; max-size=10m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-cap-add=SYS_ADMIN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-cap-add=NET_RAW&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-cap-add=CHOWN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-mount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; type=tmpfs,destination=&#x2F;var&#x2F;atlasdata,tmpfs-size=64M&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;var&#x2F;atlas-probe&#x2F;etc:&#x2F;var&#x2F;atlas-probe&#x2F;etc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;var&#x2F;atlas-probe&#x2F;status:&#x2F;var&#x2F;atlas-probe&#x2F;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; RXTXRPT=yes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ripe-atlas&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-hostname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;hostname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-fqdn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        jamesits&#x2F;ripe-atlas:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;&#x2F;strong&gt;: In the above case, since I am running the Probe on my RPi which is why I am using &lt;code&gt;latest-armv7l&lt;&#x2F;code&gt; tag for the &lt;code&gt;jamesits&#x2F;ripe-atlas&lt;&#x2F;code&gt; image. In case you are doing this on an &lt;code&gt;amd64&lt;&#x2F;code&gt; machine, you should use the &lt;code&gt;latest&lt;&#x2F;code&gt; tag only. You can find more options for the container &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Jamesits&#x2F;docker-ripe-atlas#running&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;3-apply-for-a-software-probe&quot;&gt;3. Apply for a Software Probe&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-apply-for-a-software-probe&quot; aria-label=&quot;Anchor link for: 3-apply-for-a-software-probe&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;You need to register for a software probe &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;apply&#x2F;swprobe&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and fill in the details as mentioned below.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-apply-swprobe.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ASN&lt;&#x2F;strong&gt;: You can find the ASN of your public IP by visiting &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;iptoasn.com&#x2F;&quot;&gt;ip2asn.com&lt;&#x2F;a&gt;. You need to enter your public IP here which you can find it by visiting &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ifconfig.co&#x2F;&quot;&gt;ifconfig.co&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-ip2asn.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Public Key&lt;&#x2F;strong&gt;: You need to fill the public key generated by your Probe:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;var&#x2F;atlas-probe&#x2F;etc&#x2F;probe_key.pub&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;: We are mounting the &lt;code&gt;&#x2F;var&#x2F;atlas-probe&#x2F;etc&lt;&#x2F;code&gt; on the host path inside the container at &lt;code&gt;&#x2F;var&#x2F;atlas-probe&#x2F;etc&lt;&#x2F;code&gt;. This ensures that if you stop&#x2F;remove the container, your public&#x2F;private key pair isn’t lost and there’s no need to regenerate&#x2F;apply for a Probe again. However in case you lose this, the Probe will attempt to generate a new pair and you might need to change the public key at that point of time. So be careful to take a backup of the generated key and store somewhere safe.&lt;&#x2F;p&gt;
&lt;p&gt;After submitting the form, you will receive an email which will have information about your Probe ID.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-apply-email.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;4-wait-patiently&quot;&gt;4. Wait patiently&lt;a class=&quot;zola-anchor&quot; href=&quot;#4-wait-patiently&quot; aria-label=&quot;Anchor link for: 4-wait-patiently&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;After filling the form you need to wait roughly for &lt;strong&gt;15 minutes&lt;&#x2F;strong&gt; for your probe to be added to the global network of Atlas Probes. You will receive an email saying your Probe is live now.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-confirm-email.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-measurements&quot;&gt;Creating Measurements&lt;a class=&quot;zola-anchor&quot; href=&quot;#creating-measurements&quot; aria-label=&quot;Anchor link for: creating-measurements&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It’s pretty simple to create measurements, both via UI and a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ripe-atlas-cousteau.readthedocs.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Python library&lt;&#x2F;a&gt; developed by the RIPE community. However, for the ease and convenience I will demonstrate how to create a traceroute measurement from the UI itself:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;: You get around 15 Credits&#x2F;minute for hosting a probe. In case you just deployed a probe you might not have enough credits to perform this measurement. You can come back later to do this when you have sufficient credits.&lt;&#x2F;p&gt;
&lt;p&gt;Visit the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;my&#x2F;&quot;&gt;dashboard&lt;&#x2F;a&gt; and headover to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;measurements&#x2F;&quot;&gt;Measurement&lt;&#x2F;a&gt; tab. On clicking the &lt;code&gt;Create a Measurement&lt;&#x2F;code&gt; button you will be presented a form with various options. Let’s try a Traceroute to &lt;code&gt;mrkaran.dev&lt;&#x2F;code&gt; for this measurement:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-measurement4.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To limit the number of probes, I am going to select all Probes in India, by clicking on &lt;code&gt;+New Set -wizard&lt;&#x2F;code&gt; option in the Probe Selection tab.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-measurement3.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After submitting the form, you will be presented with a Measurement ID which you can use to download the data at a later point as well.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-measurement2.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Visit the Measurement ID page and wait for a couple of minutes for all probes to perform the measurements:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-measurement1.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That’s it! You can explore other types of Measurements and different options while performing them to customise your use case.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Atlas Probes are pretty easy to host and they are crucial in giving valuable insights about how different clients connect to upstreams and spot issues in Networks. If you can host a probe, you should seriously consider doing that and help increase the number of probes in the network. As of today, the number of probes in India is just around 113 and that is seriously very less.&lt;&#x2F;p&gt;
&lt;p&gt;If you need any help hosting one, don’t hesitate to contact me on my Twitter.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and for the record, I am hosting 2 Probes currently. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;probes&#x2F;1000991&#x2F;&quot;&gt;Probe 1000991&lt;&#x2F;a&gt; hosted on my local RPi connected to my home network (ASN24560) and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atlas.ripe.net&#x2F;probes&#x2F;1001117&#x2F;&quot;&gt;Probe 1001117&lt;&#x2F;a&gt; hosted on a DigitalOcean droplet in Bengaluru (ASN14061).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ripe-my-probes.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Monitoring my home network</title>
        <published>2020-09-18T08:10:55+05:30</published>
        <updated>2020-09-18T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/isp-monitoring/"/>
        <id>https://mrkaran.dev/posts/isp-monitoring/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/isp-monitoring/">&lt;p&gt;I like monitoring &lt;em&gt;stuff&lt;&#x2F;em&gt;. That’s what I do at work and when my home ISP started giving me random problems and I decided it would be nice to monitor my home network as well. There are a couple of ways to go around this, a very popular and OSS solution is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;oss.oetiker.ch&#x2F;smokeping&#x2F;&quot;&gt;SmokePing&lt;&#x2F;a&gt;. SmokePing is written in Perl and is used to visualise network latencies. It’s quite a great solution but for my current stack which involves Prometheus and Grafana, it meant I had to deploy a standalone tool separate from my monitoring stack - something which I wanted to avoid.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;oss.oetiker.ch&#x2F;smokeping&#x2F;doc&#x2F;reading_detail.png&quot; alt=&quot;SmokePing Graphs&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So, I looked for other solutions and luckily happened to stumble upon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;oddtazz&quot;&gt;oddtazz&lt;&#x2F;a&gt; in one of the common Telegram groups where he shared his solution for the above: Telegraf ICMP &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;influxdata&#x2F;telegraf&#x2F;tree&#x2F;master&#x2F;plugins&#x2F;inputs&#x2F;ping&quot;&gt;plugin&lt;&#x2F;a&gt; and Grafana. This is exactly what I’ve been looking for but for some reason, I had wrongly assumed Telegraf needs InfluxDB to store the data. Googling a bit more, I found Telegraf &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;influxdata&#x2F;telegraf&#x2F;blob&#x2F;release-1.15&#x2F;plugins&#x2F;outputs&#x2F;prometheus_client&#x2F;README.md&quot;&gt;supports&lt;&#x2F;a&gt; Prometheus format (amongst a huge list of others!) but this wasn’t so clear in their docs.&lt;&#x2F;p&gt;
&lt;p&gt;I decided to run a Telegraf agent in my RPi connected to my home router over LAN and scrape metrics using Prometheus and visualise graphs in Grafana! For the non-patient readers, here’s what my dashboard looks like!:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ISP-Monitoring-Grafana2.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ISP-Monitoring-Grafana1.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;a class=&quot;zola-anchor&quot; href=&quot;#setup&quot; aria-label=&quot;Anchor link for: setup&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To get started, we need to download &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;influxdata&#x2F;telegraf&quot;&gt;Telegraf&lt;&#x2F;a&gt; and configure the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;influxdata&#x2F;telegraf&#x2F;tree&#x2F;master&#x2F;plugins&#x2F;inputs&#x2F;ping&quot;&gt;Ping&lt;&#x2F;a&gt; plugin. Telegraf has the concept of &lt;strong&gt;Plugins&lt;&#x2F;strong&gt; for Input, Output, Aggregating and Processing. What this basically means is that you can configure multiple input plugins like DNS, ICMP, HTTP and export the data of these plugins in a format of your choice with Output plugins.
This makes Telegraf extermely extensible, you could write a plugin (in Go) of your choice if you fancy that as well!&lt;&#x2F;p&gt;
&lt;p&gt;Here’s what my &lt;code&gt;telegraf.conf&lt;&#x2F;code&gt; looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Input plugins&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Ping plugin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ping&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;urls&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;tailscale.mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;floyd.mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1.1.1.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;kite.zerodha.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;google.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;reddit.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;twitter.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;amazon.in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;zerodha.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;count&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ping_interval&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; DNS plugin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;inputs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns_query&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  servers&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;100.101.134.59&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  domains&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;tailscale.mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;floyd.mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1.1.1.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;kite.zerodha.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;google.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;reddit.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;twitter.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;amazon.in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;zerodha.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Output format plugins&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;outputs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;prometheus_client&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  listen&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:9283&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  metric_version&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Firstly, so nice to see an &lt;em&gt;Ops&lt;&#x2F;em&gt; tool &lt;strong&gt;not&lt;&#x2F;strong&gt; using &lt;code&gt;YAML&lt;&#x2F;code&gt;. Kudos to Telegraf for that. I’d love to see other tools follow suit.&lt;&#x2F;p&gt;
&lt;p&gt;Getting back to the configuration part, &lt;code&gt;input.plugin&lt;&#x2F;code&gt; is a list of plugins that can be configured and I have configured the Ping and DNS plugin in my config. The &lt;code&gt;output&lt;&#x2F;code&gt; is in Prometheus format so it can be scraped and ingested by Prometheus’ time-series DB.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;running-telegraf&quot;&gt;Running Telegraf&lt;a class=&quot;zola-anchor&quot; href=&quot;#running-telegraf&quot; aria-label=&quot;Anchor link for: running-telegraf&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;With the above config in place, let’s try running the agent and see what metrics we get. I am using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;_&#x2F;telegraf&#x2F;&quot;&gt;official&lt;&#x2F;a&gt; Docker image to run the agent with the following config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; telegraf-agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-restart&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; always&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 9283:9283&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;PWD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;telegraf.conf:&#x2F;etc&#x2F;telegraf&#x2F;telegraf.conf:ro&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; telegraf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After running the above command, you should be able to see the metrics at &lt;code&gt;localhost:9283&#x2F;metrics&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; localhost:9283&#x2F;metrics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; head&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Total&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Received&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Xferd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Average&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Current&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;                                 Dload&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Total&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Spent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    Left&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Speed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-:--:--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-:--:--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-:--:--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     0#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; HELP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dns_query_query_time_ms&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Telegraf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; collected&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; metric&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE dns_query_query_time_ms untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns_query_query_time_ms&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;floyd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;amazon.in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rack&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rcode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NOERROR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,record_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,result&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;success&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,server&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.101.134.59&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 124.096472&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns_query_query_time_ms&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;floyd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;google.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rack&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rcode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NOERROR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,record_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,result&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;success&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,server&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.101.134.59&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 136.793673&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns_query_query_time_ms&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;floyd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;kite.zerodha.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rack&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rcode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NOERROR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,record_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,result&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;success&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,server&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.101.134.59&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 122.780946&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns_query_query_time_ms&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;floyd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rack&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rcode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NOERROR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,record_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,result&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;success&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,server&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.101.134.59&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 137.915851&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dns_query_query_time_ms&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;floyd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;twitter.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,host&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rack&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;work&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,rcode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NOERROR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,record_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,result&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;success&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;,server&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100.101.134.59&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 111.097483&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! Now, we’re all set to configure Prometheus to scrape the metrics from this target. In order to do that you need to add a new &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;concepts&#x2F;jobs_instances&#x2F;&quot;&gt;Job&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ob_name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ispmonitor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;crape_interval&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tatic_configs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;argets&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;100.94.241.54:9283&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; RPi telegraf Agent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the above config, I am plugging my Tailscale IP assigned to my RPi on the port where Telegraf agent is bound to. This is one of the &lt;strong&gt;many&lt;&#x2F;strong&gt; reasons why Tailscale is so bloody awesome! I can connect different components in my network to each other without setting up any particular firewall rules, exposing ports on a case by case basis.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Sidenote&lt;&#x2F;strong&gt;: If you haven’t read Tailscale’s &lt;strong&gt;amazing&lt;&#x2F;strong&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;blog&#x2F;how-nat-traversal-works&#x2F;&quot;&gt;NAT Traversal blog post&lt;&#x2F;a&gt;, do yourself a favour and check it out after you finish reading this one ofcourse!&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, coming back to our Prometheus setup, we can see the metrics being ingested:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;Prometheus-Telegraf-Ingest.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;show-me-the-graphs&quot;&gt;Show me the graphs&lt;a class=&quot;zola-anchor&quot; href=&quot;#show-me-the-graphs&quot; aria-label=&quot;Anchor link for: show-me-the-graphs&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now comes the exciting bit – making &lt;strong&gt;pretty&lt;&#x2F;strong&gt; graphs. First, let’s discuss what’s the most important data I can extract out of &lt;code&gt;Ping&lt;&#x2F;code&gt; and &lt;code&gt;DNS&lt;&#x2F;code&gt; plugins. These plugins export decent amount of data, but a good rule of thumb while making dashboards is to optimise signal v&#x2F;s noise ratio. We’ll do that by filtering out only the metrics that we care for.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s checkout all the metrics exported by &lt;code&gt;Ping&lt;&#x2F;code&gt; plugin:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; localhost:9283&#x2F;metrics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; TYPE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_average_response_ms untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_maximum_response_ms untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_minimum_response_ms untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_packets_received untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_packets_transmitted untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_percent_packet_loss untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_result_code untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_standard_deviation_ms untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; TYPE ping_ttl untyped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! So, from the above list of metrics, the most important ones for us are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ping_average_response_ms&lt;&#x2F;code&gt;: Avg RTT for a packet&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ping_maximum_response_ms&lt;&#x2F;code&gt;: Max RTT for a packet&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ping_percent_packet_loss&lt;&#x2F;code&gt;: % of packets lost on the way&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With just the above 3 metrics, we can answer questions like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Is my ISP suffering an outage?&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If yes, &lt;code&gt;ping_percent_packet_loss&lt;&#x2F;code&gt; should be unusually higher than normal. This usually happens when the ISP has routing is borked and that causes the packet to be routed in a less optimized way and as a side effect packet loss becomes one of the key metrics to measure here.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Is the upstream down?&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If yes, &lt;code&gt;ping_average_response_ms&lt;&#x2F;code&gt; over a recent window should be higher than a window compared to a previous time range when things were fine and dandy. This can either mean 2 things: Either your ISP isn’t routing correctly to the said upstream or the CDN&#x2F;Region where your upstream is faced an outage. This is quite a handy metric for me to monitor!&lt;&#x2F;p&gt;
&lt;p&gt;How many times have your friends complained “&lt;code&gt;xyz.com&lt;&#x2F;code&gt; isn’t working for me” and when you try to load, it’s fine from your end? There are a lot of actors at play but &lt;code&gt;ping&lt;&#x2F;code&gt; is usually the most simple and quickest way to detect whether an issue persists or not. Of course, this doesn’t work for hosts which block ICMP packets altogether. They are not rare either, like &lt;code&gt;netflix.com&lt;&#x2F;code&gt; and &lt;code&gt;github.com&lt;&#x2F;code&gt; both block ICMP probes for example. For my use case, this wasn’t a major issue as I was able to still probe a decent amount of upstreams all over the world.&lt;&#x2F;p&gt;
&lt;p&gt;With that out of the way, let’s break the dashboard into different components and see what goes behind them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ping-response-panel&quot;&gt;Ping Response Panel&lt;a class=&quot;zola-anchor&quot; href=&quot;#ping-response-panel&quot; aria-label=&quot;Anchor link for: ping-response-panel&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ping-row-panel3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To plot this, simply choose a &lt;code&gt;Stat&lt;&#x2F;code&gt; visualisation with the query &lt;code&gt;ping_average_response_ms{url=&quot;$url&quot;}&lt;&#x2F;code&gt;. Repeat this panel for the variable &lt;code&gt;$url&lt;&#x2F;code&gt; and you should be able to generate a nice row view like this.&lt;&#x2F;p&gt;
&lt;p&gt;Additonally you can choose Thresholds and the Unit to be displayed in the panel with these options.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ping-row-panel1.png&quot; alt=&quot;&quot; &#x2F;&gt;
&lt;img src=&quot;&#x2F;images&#x2F;ping-row-panel2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ping-response-time-graph&quot;&gt;Ping Response Time Graph&lt;a class=&quot;zola-anchor&quot; href=&quot;#ping-response-time-graph&quot; aria-label=&quot;Anchor link for: ping-response-time-graph&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The next graph is interesting, it lets me visualise the avg, min, max ping response time as well as the % packet loss plotted on the Y2 (right Y) axis.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;floyd-ping.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;availability-panel&quot;&gt;Availability Panel&lt;a class=&quot;zola-anchor&quot; href=&quot;#availability-panel&quot; aria-label=&quot;Anchor link for: availability-panel&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;An interesting query to calculate uptime (just in the context whether the upstream is reachable) is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;100 - avg_over_time(ping_percent_packet_loss[2m])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since I scrape metrics at an interval of &lt;code&gt;1m&lt;&#x2F;code&gt;(in order to not ping too frequently and disrupt my actual browsing experience), in this query I am averaging the data points for the metric &lt;code&gt;ping_percent_packet_loss&lt;&#x2F;code&gt; in a &lt;code&gt;[2m]&lt;&#x2F;code&gt; window.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ping-availability.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dns-response-time-graph&quot;&gt;DNS Response Time Graph&lt;a class=&quot;zola-anchor&quot; href=&quot;#dns-response-time-graph&quot; aria-label=&quot;Anchor link for: dns-response-time-graph&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We can similarly query the DNS response time by visualising the average response time for a DNS query. This might be useful only to people self-hosting their DNS servers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;telegraf-dns.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So with a pretty simple and minimal OSS solution, I was able to setup monitoring for my home network! Over the last few days whenever my ISP had slightest of trouble, I can correlate it with my metrics! I mean I still can’t do anything about it cause the other person on ISP’s customer support is “Did you try rebooting your router” – the quintessential solution to all tech problems. Wish we could reboot this entire damn 2020 as well, but one could hope!&lt;&#x2F;p&gt;
&lt;p&gt;Shoot me for any questions on my Twitter &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&quot;&gt;@mrkaran_&lt;&#x2F;a&gt; :)&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using Tailscale for home server</title>
        <published>2020-04-23T08:10:55+05:30</published>
        <updated>2020-04-23T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/home-server-updates/"/>
        <id>https://mrkaran.dev/posts/home-server-updates/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/home-server-updates/">&lt;p&gt;For those of you who are new to my blog, I had written about my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;home-server-setup&#x2F;&quot;&gt;home server setup&lt;&#x2F;a&gt; (&lt;code&gt;hydra&lt;&#x2F;code&gt;) a few months back. Since then I’ve tweaked the setup a bit and made some changes to how I organise&#x2F;deploy applications inside my cluster. I’ll be talking about the updates made so far and the reason behind them.&lt;&#x2F;p&gt;
&lt;p&gt;A brief overview of what has changed from &lt;code&gt;hydra&lt;&#x2F;code&gt; v0.1 to &lt;code&gt;hydra&lt;&#x2F;code&gt; v0.2:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Replaced &lt;strong&gt;Wireguard&lt;&#x2F;strong&gt; with &lt;strong&gt;Tailscale&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Added a new worker node (residing in DigitalOcean, Bengaluru) to the existing RPi k3s cluster.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Shifted from PiHole to Adguard DNS upstreaming to Unbound.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Containerised all workloads and deployed on K8s (using &lt;code&gt;k3s&lt;&#x2F;code&gt; platform).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The setup looks something like this now:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;home-server-hydra.png&quot; alt=&quot;arch&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let’s take a quick look at some of the above things in detail!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-tailscale&quot;&gt;Using Tailscale&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-tailscale&quot; aria-label=&quot;Anchor link for: using-tailscale&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So, before we jump to why I started using Tailscale, let’s address a few things about Wireguard which bothered me.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Adding new devices is a real PITA and quite often laziness kicks in to generate a QR code or Private&#x2F;Public key pair. So, for those of you unaware, Wireguard needs a client config to add the server endpoint and it’s public key for the client to communicate with the server. You need to add the client’s private key on the server-side as well for the exchange of encrypted packets to happen. Doing all of this manually has been one of the reasons I’ve not added&#x2F;updated my devices as regularly as I’d like to do. For eg, on my recently bought iPad, I just haven’t bothered to do all of this, cause ugh I am lazy?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Having a central VPN server to talk to my RPi from my local network just doesn’t &lt;em&gt;seem&lt;&#x2F;em&gt; right you know? Especially when both devices are literally lying in the same room, sending the packets to a server somewhere in Electronic City (DO, blr region) from JP Nagar (where I live) feels like totally unnecessary. I really needed a mesh network to reduce wasted bandwidth and latencies. Having a central VPN server is also a SPOF, not that my home-server runs any mission-critical workloads, but still good to avoid where we can. Where else can I flex my ops-chops skills if not my home server, eh?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I started looking at different mesh VPN setups and Tailscale attracted me the most. I heard about Tailscale first time when I saw &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bradfitz.com&#x2F;2020&#x2F;01&#x2F;27&#x2F;leaving-google&quot;&gt;bradfitz’s&lt;&#x2F;a&gt; post about leaving Google and joining Tailscale on HN. Interestingly, Tailscale is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.zx2c4.com&#x2F;wireguard-go&#x2F;about&#x2F;&quot;&gt;wireguard-go&lt;&#x2F;a&gt; (the userspace implementation of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wireguard.com&#x2F;&quot;&gt;Wireguard&lt;&#x2F;a&gt; kernel module). Since I was already familiar with Wireguard and had been using it for almost a year, I got curious on Tailscale.&lt;&#x2F;p&gt;
&lt;p&gt;Tailscale basically sets up a &lt;em&gt;point-to-point&lt;&#x2F;em&gt; &lt;strong&gt;encrypted network&lt;&#x2F;strong&gt; across all your devices. What that means is there’s no “relay” (like Wireguard server) and clients can talk to each other &lt;em&gt;directly&lt;&#x2F;em&gt;. While it may seem that it is easy to set this up with a bunch of shell scripting-foo (just add all Wireguard peers in each peer config), Tailscale attempts to do a &lt;em&gt;lot&lt;&#x2F;em&gt; of the heavy lifting by making the network seamless and handling authentication.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;coordination-server&quot;&gt;Coordination Server&lt;a class=&quot;zola-anchor&quot; href=&quot;#coordination-server&quot; aria-label=&quot;Anchor link for: coordination-server&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;So, when we add a new device to Wireguard server, we basically need to generate a private&#x2F;public key pair as explained above. When you’re setting up Tailscale agent, it does all of this in the background and asks you to authorise to a central co-ordination server. Now, this server is only used to exchange information about each peer in your network. The tailscale agent uploads the private&#x2F;public key information of the peer you are currently on and any time any new peer joins the network, all of the agents’ configurations are updated real-time. The coordination server periodically checks for any new changes and pushes the updates to the agent on each node.&lt;&#x2F;p&gt;
&lt;p&gt;The real juice is that they authenticate via OAuth, OIDC or SAML. Which means that you can use your existing 2FA configurations to authenticate a new node in the network. However, this might be a point of concern for some users, but I chose convenience here. Also, since the traffic flows through the nodes directly, and is encrypted there’s not much to worry here. I’ve been following Tailscale closely and they do plan to opensource the co-ordination server in future, so maybe when that happens I’ll self-host it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nat-traversal&quot;&gt;NAT Traversal&lt;a class=&quot;zola-anchor&quot; href=&quot;#nat-traversal&quot; aria-label=&quot;Anchor link for: nat-traversal&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Apart from handling the auth, Tailscale does a pretty good job at handling connectivity across different network topologies. So, basically, if you want to peer 2 devices over the public internet you’d need to perform NAT Traversal. There are several NAT hole punching techniques which allow traversing NAT but since they are not standardised and sometimes due to erratic NAT behaviour, it poses quite a challenge to do it &lt;em&gt;seamlessly&lt;&#x2F;em&gt;. And, I’m not even talking about roaming networks as of yet.&lt;&#x2F;p&gt;
&lt;p&gt;Tailscale agents can perform NAT traversal using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;id&#x2F;draft-ietf-ice-rfc5245bis-13.html&quot;&gt;ICE&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc5389&quot;&gt;STUN&lt;&#x2F;a&gt;. What all of this practically means is if you’re sitting in a cafe somewhere and you want to access any of your internal service it &lt;strong&gt;is&lt;&#x2F;strong&gt; possible without messing around any firewall ports :D&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;&#x2F;strong&gt;: I decided to give Tailscale a shot and was quite impressed by how easy it was to setup. You can refer to the official docs for more instructions but I was able to set it up across 2 RPis and have them talk to each other under 15 minutes. I think that’s quite an awesome feat in itself. The only sad bit is they don’t have an Android app yet, so I am eagerly waiting for it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hybrid-k3s-cluster&quot;&gt;Hybrid K3s Cluster&lt;a class=&quot;zola-anchor&quot; href=&quot;#hybrid-k3s-cluster&quot; aria-label=&quot;Anchor link for: hybrid-k3s-cluster&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So, I am running a &lt;code&gt;k3s&lt;&#x2F;code&gt; cluster on my RPi. At that time I was still using DO for running Pihole, Unbound, public DNSCrypt resolver etc. I decided to standardise the ad-hoc deployments to manage them efficiently. It also allowed me to play around with more on K8s which was my original goal behind buying these Pi was.&lt;&#x2F;p&gt;
&lt;p&gt;Now, I’ve 2*RPi nodes, the k8s master node runs on the 4GB RPi while the 2GB variant serves as a worker node. I decided to get a bit fancy with my setup and hooked up the &lt;code&gt;k3s&lt;&#x2F;code&gt; agent installation script on a DO node and&lt;em&gt;ta-da!&lt;&#x2F;em&gt; I have a multi-arch(&lt;code&gt;amd64&lt;&#x2F;code&gt; and &lt;code&gt;arm64&lt;&#x2F;code&gt;), hybrid (bare metal and cloud) K8s cluster ready! I think if I sprinkle some ML&#x2F;AI + Bitcoins in the above setup, I’m all set to raise VC funding for &lt;code&gt;hydra&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I wanted to learn &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.terraform.io&#x2F;&quot;&gt;Terraform&lt;&#x2F;a&gt; as part of my work at my org as well, so I created + managed the entire droplet through &lt;code&gt;terraform&lt;&#x2F;code&gt;. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;hydra&#x2F;tree&#x2F;master&#x2F;digitalocean-infra&quot;&gt;script&lt;&#x2F;a&gt; has modules to provision a droplet, attach an elastic IP, configure firewall rules and add my SSH key to the server. Quite easy to manage and I am generally a hater of GUIs, so Terraform is indeed a blessing in disguise.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I know some of my opinions are a bit strong but don’t worry I get meme’d&#x2F;burnt for this almost every day by my work colleagues.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;pihole-to-adguard&quot;&gt;Pihole to Adguard&lt;a class=&quot;zola-anchor&quot; href=&quot;#pihole-to-adguard&quot; aria-label=&quot;Anchor link for: pihole-to-adguard&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;While Pihole works really well for blocking Ads it had some features lacking, particularly DOT and DOH support &lt;strong&gt;out of the box&lt;&#x2F;strong&gt;. I decided I’ll shift to Adguard as the codebase is in Go - something which I am a bit familiar with and also the UI feels a bit sleek and refreshing too!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;adguard-dns.png&quot; alt=&quot;adguard&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;accessing-internal-services&quot;&gt;Accessing internal services&lt;a class=&quot;zola-anchor&quot; href=&quot;#accessing-internal-services&quot; aria-label=&quot;Anchor link for: accessing-internal-services&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A major challenge for me was however to configure access to internal services on the K8s cluster. Since I have bare metal worker nodes, it’s not possible to deploy a cloud load balancer. For now, I went with a really simple old school solution, to expose an Nginx proxy front-ending all my services through NodePort. I am planning to look at Traefik or Istio for this but I wanted to just shipit! at this point.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s a very basic example of an &lt;code&gt;nginx&lt;&#x2F;code&gt; config for &lt;code&gt;ip.mrkaran.dev&lt;&#x2F;code&gt; that I run on my cluster:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;server {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        server_name ip.mrkaran.dev;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        # reverse proxy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        location &#x2F; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                proxy_pass http:&#x2F;&#x2F;100.96.239.6:30506; # tailscale IP, connecting to NodePort service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                include fluff&#x2F;proxy.conf;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;30506&lt;&#x2F;code&gt; port is exposed by the &lt;code&gt;Service&lt;&#x2F;code&gt; object backing up the pods for that application. Since a &lt;code&gt;NodePort&lt;&#x2F;code&gt; service is available on any K8s node, you can give the Tailscale IP for any node and the routing will be handled by &lt;code&gt;kube-proxy&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;challenges-faced&quot;&gt;Challenges faced&lt;a class=&quot;zola-anchor&quot; href=&quot;#challenges-faced&quot; aria-label=&quot;Anchor link for: challenges-faced&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mesh-or-mess&quot;&gt;Mesh or mess&lt;a class=&quot;zola-anchor&quot; href=&quot;#mesh-or-mess&quot; aria-label=&quot;Anchor link for: mesh-or-mess&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Setting all of this up didn’t come without its own challenges or hurdles. Right off the bat, the first problem was that I was seeing really high latencies from my RPi node to DO node through Tailscale. Now, since both the nodes are physically in Bangalore and they are connecting to each other (or that’s what I had presumed), I didn’t expect latencies to be as high as 500-600ms. Bollocks!&lt;&#x2F;p&gt;
&lt;p&gt;Eventually, I’d figured thanks to my super restrictive rules on the firewall of DO node, I had blocked all inbound UDP connection. That means NAT hole punching through STUN is simply not possible. In such cases, Tailscale forwards all packets to an encrypted TURN server(called DERP - Designated Encrypted Relay for Packets), which basically are TCP encrypted relays. Tailscale manages this network of DERPs and the one I got connected to was somewhere in the USA.&lt;&#x2F;p&gt;
&lt;p&gt;Bottom line, I was all pumped up to talk to a DO node from my RPi node but as it &lt;em&gt;turns&lt;&#x2F;em&gt; out (no pun intended) my packets were flowing through the USA! Ah so bad. Anyway, opening up UDP from the Tailscale subnet, fixed the issue and latencies were back to being sub 10ms. Yay!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;overlay-over-an-overlay&quot;&gt;Overlay over an overlay&lt;a class=&quot;zola-anchor&quot; href=&quot;#overlay-over-an-overlay&quot; aria-label=&quot;Anchor link for: overlay-over-an-overlay&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Next up, were problems with K3s networking from the DO node to RPi node. The DO node was in a &lt;code&gt;NotReady&lt;&#x2F;code&gt; state because the agent couldn’t reach the server:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Apr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 14&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 09:00:33&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hydra-control&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; k3s[19746]:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; I0414&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 09:00:33.306650&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;   19746&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; log.go:172]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; TLS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; handshake&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; error&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 100.97.222.106:51516:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; read&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 100.96.239.6:6443&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;100.97.222.106:51516:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; read:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; reset&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; by&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; peer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Through some trial and error and reading the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rancher.com&#x2F;docs&#x2F;k3s&#x2F;latest&#x2F;en&#x2F;networking&#x2F;&quot;&gt;docs&lt;&#x2F;a&gt;, I figured that &lt;code&gt;flannel&lt;&#x2F;code&gt; is running as a CNI in &lt;code&gt;k3s&lt;&#x2F;code&gt;. Now the problem is flannel itself is an overlay network. But… Tailscale already is an overlay network (Wireguard) so the packets are not being routed correctly and being dropped halfway in the master node (I am guessing the DNAT&#x2F;SNAT translation botched up here).&lt;&#x2F;p&gt;
&lt;p&gt;The trick was to just &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;hydra&#x2F;blob&#x2F;master&#x2F;pi&#x2F;roles&#x2F;k3s-control&#x2F;templates&#x2F;k3s-control.service.j2#L13&quot;&gt;change&lt;&#x2F;a&gt; flannel backend to run in the host namespace only. That solved the above issue for me.&lt;&#x2F;p&gt;
&lt;p&gt;However, I still had one more issue. The DO node’s &lt;strong&gt;public&lt;&#x2F;strong&gt; IP was being advertised, while the agent was running on Tailscale network interface so the master was never able to reach the agent. Similarly, when the agent tried to communicate with the server, the private IP of the node was being advertised.
Setting the &lt;code&gt;--node-external-ip &amp;lt;tailscale-ip&amp;gt;&lt;&#x2F;code&gt; in &lt;code&gt;k3s&lt;&#x2F;code&gt; config seemed to have fixed the problem.&lt;&#x2F;p&gt;
&lt;p&gt;Now all of the nodes in the cluster had proper Tailscale IPs advertised and the node went to &lt;code&gt;Ready&lt;&#x2F;code&gt; state, at last!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;who-let-the-dns-out&quot;&gt;Who let the DNS out&lt;a class=&quot;zola-anchor&quot; href=&quot;#who-let-the-dns-out&quot; aria-label=&quot;Anchor link for: who-let-the-dns-out&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;So, I’ve a chicken and egg problem in my setup. Since my &lt;code&gt;laptop&lt;&#x2F;code&gt; runs a Tailscale agent and whenever I boot up my systemm, &lt;code&gt;Tailscale&lt;&#x2F;code&gt; attempts to posts logs to &lt;code&gt;log.tailsclae.io&lt;&#x2F;code&gt; and &lt;strong&gt;fails&lt;&#x2F;strong&gt; to start if it cannot. The problem here is who resolves the DNS for me?&lt;&#x2F;p&gt;
&lt;p&gt;I run a local DNS server with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;coredns.io&#x2F;&quot;&gt;CoreDNS&lt;&#x2F;a&gt; forwarding my queries to Adguard. Now if I can’t reach Adguard (since Tailscale agent hasn’t initialised), how am I supposed to resolve &lt;code&gt;log.tailscale.io&lt;&#x2F;code&gt;? I did what any sane guy would do, write a simple &lt;em&gt;hacky&lt;&#x2F;em&gt; bash script:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; chattr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;resolv.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nameserver 1.1.1.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;resolv.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;changed dns server to 1.1.1.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tailscale&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nameserver 127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;resolv.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;changed dns server back to 127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; chattr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;resolv.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yes, it’s quite insane. Also, I’ve not been able to figure out how to stop &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; from changing my &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; so I rely on a hack (documented in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Domain_name_resolution#Overwriting_of_&#x2F;etc&#x2F;resolv.conf&quot;&gt;Arch official docs&lt;&#x2F;a&gt;), to &lt;code&gt;lock&lt;&#x2F;code&gt; the file so any process cannot modify it. Quirky, but works!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;storage&quot;&gt;Storage&lt;a class=&quot;zola-anchor&quot; href=&quot;#storage&quot; aria-label=&quot;Anchor link for: storage&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Unfortunately, I don’t have any external HDD&#x2F;SSD so I am postponing running any stateful workloads till I get one soon (whenever lockdown gets over in my area). I plan to deploy an NFS server so I can run stateful workloads across any node and have redundancy in form of cloud backups. I’ve also heard cool things about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;longhorn&#x2F;longhorn&quot;&gt;Longhorn&lt;&#x2F;a&gt; but unfortunately, it doesn’t have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;longhorn&#x2F;longhorn&#x2F;issues&#x2F;6&quot;&gt;ARM support&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Well, I am quite stoked by my current setup right now. Learnt a bunch of cool things around NAT traversal, zero-trust networking, realised the old days of LAN were so much better (not that I am that old to have experienced, my first internet connection was rather broadband at home, not even dial-up). Tailscale opens up a lot of new opportunities for corporate VPNs and it is something definitely to watch out for as they continue improving the product.&lt;&#x2F;p&gt;
&lt;p&gt;Also, I was super elated when &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;bradfitz&quot;&gt;bradfitz&lt;&#x2F;a&gt; himself had commented on my tweet, not gonna lie!&lt;&#x2F;p&gt;
&lt;p&gt;{{&amp;lt; tweet 1249552822674149376 &amp;gt;}}&lt;&#x2F;p&gt;
&lt;h3 id=&quot;credits&quot;&gt;Credits&lt;a class=&quot;zola-anchor&quot; href=&quot;#credits&quot; aria-label=&quot;Anchor link for: credits&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;First, a major thanks to my friend &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.saratchandra.in&quot;&gt;sarat&lt;&#x2F;a&gt; with whom I pair debugged a lot of the above issues and since he also runs a home server, he was my go-to person to ask doubts!&lt;&#x2F;p&gt;
&lt;p&gt;Here are some links that I collected while setting all of this up and might be useful as references if you’re planning a similar setup!&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;blog&#x2F;how-tailscale-works&#x2F;&quot;&gt;How Tailscale Works&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;kb&#x2F;1015&#x2F;100.x-addresses&quot;&gt;What are these 100.x.y.z addresses?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rancher.com&#x2F;docs&#x2F;k3s&#x2F;latest&#x2F;en&#x2F;installation&#x2F;install-options&#x2F;server-config&#x2F;&quot;&gt;k3s config reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bford.info&#x2F;pub&#x2F;net&#x2F;p2pnat&#x2F;&quot;&gt;P2P across NAT&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crawshaw.io&#x2F;blog&#x2F;remembering-the-lan&quot;&gt;Remembering the LAN&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;app.cloudskew.com&#x2F;&quot;&gt;Cloudskew&lt;&#x2F;a&gt; (wonderful tool for creating architecture diagrams)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you’ve any questions please find me on Twitter &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&quot;&gt;@mrkaran&lt;&#x2F;a&gt;. You can find all of the setup on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;hydra&#x2F;&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Till next time, if we survive the pandemic!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>DNS Lookups in Kubernetes</title>
        <published>2020-02-02T10:57:55+05:30</published>
        <updated>2020-02-02T10:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/ndots-kubernetes/"/>
        <id>https://mrkaran.dev/posts/ndots-kubernetes/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/ndots-kubernetes/">&lt;p&gt;One of the primary advantages of deploying workloads in Kubernetes is seamless application discovery. Intra cluster communication becomes easy with the concept of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;&quot;&gt;Service&lt;&#x2F;a&gt; which represents a Virtual IP backing a set of Pod IPs. For example, if &lt;code&gt;vanilla&lt;&#x2F;code&gt; service needs to talk to a &lt;code&gt;chocolate&lt;&#x2F;code&gt; service, it can directly use the Virtual IP for &lt;code&gt;chocolate&lt;&#x2F;code&gt;. Now the question is who resolves the DNS query for &lt;code&gt;chocolate&lt;&#x2F;code&gt; and how?&lt;&#x2F;p&gt;
&lt;p&gt;DNS resolution is configured in Kubernetes cluster through &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;coredns.io&#x2F;&quot;&gt;CoreDNS&lt;&#x2F;a&gt;. The kubelet configures each Pod’s &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; to use the coredns pod as the &lt;code&gt;nameserver&lt;&#x2F;code&gt;. You can see the contents of &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; inside any pod, they’ll look something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;search&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hello.svc.cluster.local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; svc.cluster.local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cluster.local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nameserver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.152.183.10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ndots:5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This config is used by DNS clients to forward the DNS queries to a DNS server. &lt;code&gt;resolv.conf&lt;&#x2F;code&gt; is the resolver configuration file which has information about:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;nameserver&lt;&#x2F;strong&gt; : Where the DNS queries are forwarded to. In our case this is the address of &lt;code&gt;CoreDNS&lt;&#x2F;code&gt; service.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;search&lt;&#x2F;strong&gt;: Represents the search path for a particular domain. Interestingly &lt;code&gt;google.com&lt;&#x2F;code&gt; or &lt;code&gt;mrkaran.dev&lt;&#x2F;code&gt; is not FQDN (fully qualified domain name). A standard convention that most DNS resolvers follow is that if a domain ends with &lt;code&gt;.&lt;&#x2F;code&gt; (representing the root zone), the domain is considered to be FQDN. Some resolvers try to act smart and append the &lt;code&gt;.&lt;&#x2F;code&gt; themselves. So &lt;code&gt;mrkaran.dev.&lt;&#x2F;code&gt; is an FQDN but &lt;code&gt;mrkaran.dev&lt;&#x2F;code&gt; is not.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ndots&lt;&#x2F;strong&gt;: This is the most interesting value and is the &lt;em&gt;highlight&lt;&#x2F;em&gt; of this post. &lt;code&gt;ndots&lt;&#x2F;code&gt; represents the threshold value of the number of dots in a query name to consider it as a “fully qualified” domain name. More on this later, as we discover the flow of DNS lookup.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;dns-k8s.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let’s check what happens when we query for &lt;code&gt;mrkaran.dev&lt;&#x2F;code&gt; in a pod.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nslookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.152.183.10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Address:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.152.183.10#53&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Non-authoritative&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; answer:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Name:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Address:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 157.230.35.153&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Name:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Address:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 2400:6180:0:d1::519:6001&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For this experiment, I’ve also turned on CoreDNS logging level to &lt;code&gt;all&lt;&#x2F;code&gt; which makes it highly verbose. Let’s look at the logs of &lt;code&gt;coredns&lt;&#x2F;code&gt; pod:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:35998 - 11131 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran.dev.hello.svc.cluster.local. udp 53 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,aa,rd 146 0.000263728s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:34040 - 36853 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran.dev.svc.cluster.local. udp 47 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,aa,rd 140 0.000214201s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:33468 - 29482 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran.dev.cluster.local. udp 43 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,aa,rd 136 0.000156107s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:58471 - 45814 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran.dev. udp 29 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NOERROR qr,rd,ra 56 0.110263459s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:54800 - 2463 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;AAAA IN mrkaran.dev. udp 29 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NOERROR qr,rd,ra 68 0.145091744s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whew. So 2 things piqued my interest here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The query iterates through all search paths until the answer contains a &lt;code&gt;NOERROR&lt;&#x2F;code&gt; code (which the DNS clients understand and store it as the result). &lt;code&gt;NXDOMAIN&lt;&#x2F;code&gt; simply indicates no record found for that domain name. Since &lt;code&gt;mrkaran.dev&lt;&#x2F;code&gt; isn’t an FQDN (according to &lt;code&gt;ndots=5&lt;&#x2F;code&gt; setting), the resolver looks at search path and determines the order of query.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;A&lt;&#x2F;code&gt; and &lt;code&gt;AAAA&lt;&#x2F;code&gt; records are fired parallelly. This is because &lt;code&gt;single-request&lt;&#x2F;code&gt; option in &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; has a default configuration to perform parallel IPv4 and IPv6 lookups. You can disable this using &lt;code&gt;single-request&lt;&#x2F;code&gt; option.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Note&lt;&#x2F;em&gt;: &lt;code&gt;glibc&lt;&#x2F;code&gt; can be configured to send these requests sequentially but &lt;code&gt;musl&lt;&#x2F;code&gt; cannot, so Alpine users must take note.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;playing-around-with-ndots&quot;&gt;Playing around with ndots&lt;a class=&quot;zola-anchor&quot; href=&quot;#playing-around-with-ndots&quot; aria-label=&quot;Anchor link for: playing-around-with-ndots&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Let’s play around with &lt;code&gt;ndots&lt;&#x2F;code&gt; a bit more and see how it behaves. The idea is simple, for the DNS client to know whether a domain is an absolute one or not is through this &lt;code&gt;ndots&lt;&#x2F;code&gt; setting. For example, if you query for &lt;code&gt;google&lt;&#x2F;code&gt; simply, how will the DNS client know if this is an absolute domain. If you set &lt;code&gt;ndots&lt;&#x2F;code&gt; as &lt;code&gt;1&lt;&#x2F;code&gt;, the DNS client will say “oh, &lt;code&gt;google&lt;&#x2F;code&gt; doesn’t have even one 1 dot, let me try going through search list. However, if you query for &lt;code&gt;google.com&lt;&#x2F;code&gt;, the search list will be completely ignored since the query name satisfies the &lt;code&gt;ndots&lt;&#x2F;code&gt; threshold (At least one dot).&lt;&#x2F;p&gt;
&lt;p&gt;We can see this by actually doing it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;resolv.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ndots:1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nslookup&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Server:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.152.183.10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Address:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.152.183.10#53&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; server can&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t find mrkaran: NXDOMAIN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;CoreDNS logs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:52495 - 2606 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran.hello.svc.cluster.local. udp 49 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,aa,rd 142 0.000524939s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:59287 - 57522 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran.svc.cluster.local. udp 43 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,aa,rd 136 0.000368277s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:53086 - 4863 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran.cluster.local. udp 39 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,aa,rd 132 0.000355344s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;INFO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; 10.1.28.1:56863 - 41678 &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A IN mrkaran. udp 25 false 512&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; NXDOMAIN qr,rd,ra 100 0.034629206s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since &lt;code&gt;mrkaran&lt;&#x2F;code&gt; didn’t specify any &lt;code&gt;.&lt;&#x2F;code&gt; so the search list was used to find the answer.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;&#x2F;em&gt;: &lt;code&gt;ndots&lt;&#x2F;code&gt; value is silently capped to &lt;code&gt;15&lt;&#x2F;code&gt; and is &lt;code&gt;5&lt;&#x2F;code&gt; in Kubernetes as default.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;handling-this-in-production&quot;&gt;Handling this in Production&lt;a class=&quot;zola-anchor&quot; href=&quot;#handling-this-in-production&quot; aria-label=&quot;Anchor link for: handling-this-in-production&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If your application is of the nature that makes a lot of external network calls, the DNS can become a bottleneck in case of heavy traffic since a lot of extra queries are made before the real DNS query is even fired. It’s quite uncommon to see applications appending the root zone in the domain names, but that can be considered as a hack. So instead of using &lt;code&gt;api.twitter.com&lt;&#x2F;code&gt;, you can hardcode your application to include &lt;code&gt;api.twitter.com.&lt;&#x2F;code&gt; which would force the DNS clients to do an authoritative lookup directly on the absolute domain.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, since K8s 1.14, the &lt;code&gt;dnsConfig&lt;&#x2F;code&gt; and &lt;code&gt;dnsPolicy&lt;&#x2F;code&gt; feature gates have become stable. So while deploying a pod you can specify &lt;code&gt;ndots&lt;&#x2F;code&gt; setting to something lesser, say &lt;code&gt;3&lt;&#x2F;code&gt; or if you want to be really aggressive you can turn it down to &lt;code&gt;1&lt;&#x2F;code&gt;. The consequences of this will be that every intra-node communication now has to include the full domain. This is one of the classic tradeoffs where you have to choose between performance and portability. If the app doesn’t demand super low latencies, I guess you need not worry about this at all since DNS results are cached internally too.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;a class=&quot;zola-anchor&quot; href=&quot;#references&quot; aria-label=&quot;Anchor link for: references&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I got to know about this peculiarity first, in a K8s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;failuremodes.dev&#x2F;&quot;&gt;meetup&lt;&#x2F;a&gt; which I went to, last weekend where the folks mentioned about having to deal with this.&lt;&#x2F;p&gt;
&lt;p&gt;Here are some additional links you can read on the web:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;kubernetes&#x2F;issues&#x2F;33554#issuecomment-266251056&quot;&gt;Explainer on why ndots=5 in kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pracucci.com&#x2F;kubernetes-dns-resolution-ndots-options-and-why-it-may-affect-application-performances.html&quot;&gt;Great read on how ndots affects application performance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.openwall.com&#x2F;lists&#x2F;musl&#x2F;2017&#x2F;03&#x2F;15&#x2F;3&quot;&gt;musl and glibc resolver inconsistencies&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Note&lt;&#x2F;em&gt;: I’m particularly not using &lt;code&gt;dig&lt;&#x2F;code&gt; in this post. &lt;code&gt;dig&lt;&#x2F;code&gt; apparently automatically adds a &lt;code&gt;.&lt;&#x2F;code&gt; (root zone identifier) to make the domain an FQDN one &lt;strong&gt;without&lt;&#x2F;strong&gt; even first going through the search path. I’ve mentioned about this briefly in one of my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;dig-overview&#x2F;&quot;&gt;older&lt;&#x2F;a&gt; posts. Nonetheless, it’s quite surprising to see that you need to give a flag to make it behave in what seems to be a standard way.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;it-s-always-dns-isn-t-it&quot;&gt;It’s always DNS, isn’t it ;)&lt;a class=&quot;zola-anchor&quot; href=&quot;#it-s-always-dns-isn-t-it&quot; aria-label=&quot;Anchor link for: it-s-always-dns-isn-t-it&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;update&quot;&gt;Update&lt;a class=&quot;zola-anchor&quot; href=&quot;#update&quot; aria-label=&quot;Anchor link for: update&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;2020-12-24&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;In case you want to play around with &lt;code&gt;ndots&lt;&#x2F;code&gt; and DNS more, I’ve worked on a DNS Client which lets you tweak these params on the fly. Feel free to checkout &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;doggo&quot;&gt;doggo&lt;&#x2F;a&gt; if interested!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Resize PVC in Kubernetes</title>
        <published>2020-01-14T08:10:55+05:30</published>
        <updated>2020-01-14T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/resize-pvc-k8s/"/>
        <id>https://mrkaran.dev/posts/resize-pvc-k8s/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/resize-pvc-k8s/">&lt;p&gt;Well, the title is self explanatory so let’s begin!&lt;&#x2F;p&gt;
&lt;p&gt;First off, we need to ensure that the &lt;code&gt;StorageClass&lt;&#x2F;code&gt; which was used to provision the PVC has the correct configuration. From the official &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;persistent-volumes&#x2F;&quot;&gt;docs&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can only expand a PVC if its storage class’s allowVolumeExpansion field is set to true.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So, let’s inspect our storage class:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kubectl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; sc is short for storageclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            PROVISIONER&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;             AGE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;gp2&lt;&#x2F;span&gt;&lt;span&gt; (default&lt;&#x2F;span&gt;&lt;span&gt;)   kubernetes.io&#x2F;aws-ebs   8d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kubectl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; describe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sc&#x2F;gp2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; output redacted to focus only on the field we&amp;#39;re concerned with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Name:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;            gp2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;AllowVolumeExpansion:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If &lt;code&gt;AllowVolumeExpansion&lt;&#x2F;code&gt; is set to &lt;code&gt;True&lt;&#x2F;code&gt; you can skip the below step. If it’s not true, you need edit the field &lt;code&gt;allowVolumeExpansion&lt;&#x2F;code&gt; as &lt;code&gt;true&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;piVersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;torage.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;torageClass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etadata&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nnotations&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;torageclass.kubernetes.io&#x2F;is-default-class&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;true&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arameters&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;sType&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;xt4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rovisioner&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ubernetes.io&#x2F;aws-ebs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;eclaimPolicy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;elete&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumeBindingMode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; W&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;aitForFirstConsumer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;llowVolumeExpansion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once the &lt;code&gt;StorageClass&lt;&#x2F;code&gt; config is correct, all we need to do is update with the new size.&lt;&#x2F;p&gt;
&lt;p&gt;So, for example if size of the PVC was &lt;code&gt;15GB&lt;&#x2F;code&gt; orginally:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;pec&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;esources&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;equests&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;torage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5Gi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To update it to &lt;code&gt;30GB&lt;&#x2F;code&gt;, you simply need to edit &lt;code&gt;spec.resources.requests&lt;&#x2F;code&gt; field:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;pec&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;esources&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;equests&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;torage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0Gi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We now need to “apply” the updated PVC manifest.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kubectl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pvc.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s take a look at the PVC:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kubectl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; describe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pvc&#x2F;myclaim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; output redacted for brevity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Conditions:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                      Status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  LastProbeTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                     LastTransitionTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                Reason&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  ----&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;                      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-----&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;----------------&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;                 -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-----------------&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;                -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-----&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  FileSystemResizePending&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   True&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    Mon,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Jan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 0001&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 00:00:00&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +0000&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Tue,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 14&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Jan&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2020&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 20:52:21&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +0530&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;           Waiting&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span&gt; (re-&lt;&#x2F;span&gt;&lt;span&gt;)start a pod to finish file system resize of volume on node.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, basically what &lt;code&gt;FileSystemResizePending&lt;&#x2F;code&gt; means is that while PVC is &lt;em&gt;in use&lt;&#x2F;em&gt;, we have to either restart or delete the underlying Pod using the PVC. At the time of writing this, &lt;code&gt;ExpandInUsePersistentVolumes&lt;&#x2F;code&gt; is still in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;persistent-volumes&#x2F;#resizing-an-in-use-persistentvolumeclaim&quot;&gt;beta&lt;&#x2F;a&gt; and has to be enabled as a feature gate. Sadly, EKS is still on &lt;code&gt;1.14&lt;&#x2F;code&gt; (while the world has moved to 1.17, such &lt;em&gt;sloooow&lt;&#x2F;em&gt; release cycles!), so I couldn’t enable this in my case.&lt;&#x2F;p&gt;
&lt;p&gt;Once the pod is restarted, the expanded disk is automagically available! Let’s verify this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kc get pvc&#x2F;myclaim -o=jsonpath=&amp;quot;{.status.capacity.storage}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;30Gi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, compare this with the standard way of resizing an EBS volume in EC2 instance. You need to first &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AWSEC2&#x2F;latest&#x2F;UserGuide&#x2F;requesting-ebs-volume-modifications.html#modify-ebs-volume-cli&quot;&gt;modify&lt;&#x2F;a&gt; the volume size using AWS EBS API and then in the EC2 instance, use a combination of &lt;code&gt;growpart&lt;&#x2F;code&gt; and &lt;code&gt;resize2fs&lt;&#x2F;code&gt; to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AWSEC2&#x2F;latest&#x2F;UserGuide&#x2F;recognize-expanded-volume-linux.html&quot;&gt;extend&lt;&#x2F;a&gt; the resized volume. This sounds much more cumbersome than simply updating the storage field in PVC manifest!&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>sshuttle - A better ssh tunnel</title>
        <published>2020-01-12T09:57:55+05:30</published>
        <updated>2020-01-12T09:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/using-sshuttle/"/>
        <id>https://mrkaran.dev/posts/using-sshuttle/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/using-sshuttle/">&lt;h2 id=&quot;the-motivation&quot;&gt;The Motivation&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-motivation&quot; aria-label=&quot;Anchor link for: the-motivation&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Sometime back I had to access a Kubernetes API server which was firewalled to a private VPC network. I didn’t want to setup a separate bastion instance just to access this cluster, cause TBH bastions are kinda redundant in K8s as every task can be performed through the client-server APIs using &lt;code&gt;kubectl&lt;&#x2F;code&gt;. So, all I needed was access to this API server from a trusted network in a secure way. Thanks to my friend &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;iamd3vil&quot;&gt;@sarat&lt;&#x2F;a&gt;, I got to know about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sshuttle.readthedocs.io&#x2F;en&#x2F;stable&#x2F;&quot;&gt;sshuttle&lt;&#x2F;a&gt;. &lt;code&gt;sshuttle&lt;&#x2F;code&gt; is quite unique in the sense that it’s not really a VPN but acts like one (for most practical purposes). &lt;code&gt;sshuttle&lt;&#x2F;code&gt; lets you access an internal network through a trusted node inside the VPC, without you having to deal with the mess of port forwarding or VPNs.&lt;&#x2F;p&gt;
&lt;p&gt;The basic idea is pretty simple, &lt;code&gt;sshuttle&lt;&#x2F;code&gt; starts a local &lt;code&gt;python&lt;&#x2F;code&gt; server in your host machine and creates &lt;code&gt;iptables&lt;&#x2F;code&gt; rules to route the destination packets of the specified CIDR blocks to this local server. At the server, the packets are multiplexed over an &lt;code&gt;ssh&lt;&#x2F;code&gt; session and sent to the server. The server disassembles the multiplexed packet and the routes them to upstream. So, basically this is a clever hack to avoid TCP over TCP (which again is a mess on unreliable networks). Multiplexed streams on &lt;code&gt;ssh&lt;&#x2F;code&gt; is just a single stateful TCP connection (as compared to VPN connections which are stateless). Now you must be wondering, how come the target server disassembles the packets. Yes, there needs to be some kind of &lt;code&gt;sshuttle&lt;&#x2F;code&gt; daemon running which does that for you. This is where &lt;code&gt;sshuttle&lt;&#x2F;code&gt; does some magic, it &lt;em&gt;automagically&lt;&#x2F;em&gt; deploys a python script on your target host to perform this task. So yes, for &lt;code&gt;sshuttle&lt;&#x2F;code&gt; to work, both the client and target need to have &lt;code&gt;python &lt;&#x2F;code&gt; and &lt;code&gt;iptables&lt;&#x2F;code&gt; installed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;usage&quot;&gt;Usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#usage&quot; aria-label=&quot;Anchor link for: usage&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;sshuttle -r user@port x.x.x.x&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;All the packets routed to the CIDR block will now go through &lt;code&gt;sshuttle&lt;&#x2F;code&gt; daemon, since it configured &lt;code&gt;iptables&lt;&#x2F;code&gt; rules for them.
Also, &lt;code&gt;sshuttle&lt;&#x2F;code&gt; starts a local python server on your host machine. You can see it using &lt;code&gt;netstat&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; netstat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;tunapl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; python&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Proto&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Recv-Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Send-Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;           Foreign&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         State&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       PID&#x2F;Program&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 127.0.0.1:12300&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         0.0.0.0:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               LISTEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      27425&#x2F;python&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There’s a &lt;code&gt;python&lt;&#x2F;code&gt; server listening on port &lt;code&gt;12300&lt;&#x2F;code&gt; in my host machine. To actually verify, this indeed is started by &lt;code&gt;sshuttle&lt;&#x2F;code&gt;, you can use &lt;code&gt;pstree -p | less&lt;&#x2F;code&gt; and search for &lt;code&gt;sshuttle&lt;&#x2F;code&gt;. Here you can see &lt;code&gt;sshuttle&lt;&#x2F;code&gt; did indeed start a &lt;code&gt;python&lt;&#x2F;code&gt; server and the PID (&lt;code&gt;27425&lt;&#x2F;code&gt;) matches with the one we saw in &lt;code&gt;netstat&lt;&#x2F;code&gt; command.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -zsh(13201&lt;&#x2F;span&gt;&lt;span&gt;)---sshuttle(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;27425&lt;&#x2F;span&gt;&lt;span&gt;)-+-ssh(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;27446&lt;&#x2F;span&gt;&lt;span&gt;)---ssh(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;27447&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                                    `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;-sudo(27427&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;)---python(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;27445&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can even forward DNS queries with the &lt;code&gt;--dns&lt;&#x2F;code&gt; flag. This is super helpful if you have something like Route53 to host your DNS records on a private zone (for eg tld like &lt;code&gt;.internal&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;better-than-ssh-tunnels&quot;&gt;Better than SSH tunnels?&lt;a class=&quot;zola-anchor&quot; href=&quot;#better-than-ssh-tunnels&quot; aria-label=&quot;Anchor link for: better-than-ssh-tunnels&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Yes, you can also port forward with ssh using:
&lt;code&gt;ssh -nNT -L &amp;lt;local-port&amp;gt;:{upstream-host}:{upstream-port} user@remote&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The problem with &lt;code&gt;ssh&lt;&#x2F;code&gt; tunnels is that they experience frequent packet loss on a normal WiFi connection and it’s quite frustrating to deal with them. Moreover, sometimes you need access to multiple ports in your private network which requires you to explictly provide them with &lt;code&gt;-L&lt;&#x2F;code&gt; flag which I find it as cumbersome. Also, you cannot forward DNS queries (over UDP) since &lt;code&gt;ssh&lt;&#x2F;code&gt; can only do TCP.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;sshuttle&lt;&#x2F;code&gt; has made my life so simple!&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Use netcat for port scanning</title>
        <published>2020-01-11T08:10:55+05:30</published>
        <updated>2020-01-11T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/netcat-port/"/>
        <id>https://mrkaran.dev/posts/netcat-port/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/netcat-port/">&lt;p&gt;Quite often you’d need to check if a port on a target node is opened or blocked by firewall. I’ve always used &lt;code&gt;telnet&lt;&#x2F;code&gt; to test that but it has a few drawbacks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Need to use dirty &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;41476089&#x2F;auto-exit-telnet-command-back-to-prompt-without-human-intervention-quit-close&quot;&gt;hacks&lt;&#x2F;a&gt; in shell scripts to auto close the connection. Also, telnet outputs some errors to &lt;code&gt;&#x2F;dev&#x2F;stdout&lt;&#x2F;code&gt; instead of the standard &lt;code&gt;&#x2F;dev&#x2F;stderr&lt;&#x2F;code&gt; which makes it harder to use in scripts.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Non standard implementation across different OSes. On Alpine Linux (mostly used in containers), if you install telnet using the &lt;code&gt;&#x2F;busybox-extras&lt;&#x2F;code&gt; package, the behaviour is different from what it is on standard Ubuntu&#x2F;Arch environments. I’ve even faced weird issues on Alpine where telnet will simply wait endlessley for the connection to be established, while netcat would not indicate any issues.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Telnet is actually a protocol and the telnet-client initiates the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;mud-dev.wikidot.com&#x2F;telnet:negotiation&quot;&gt;negotiation&lt;&#x2F;a&gt; with the server before a connection is established.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So, after all these issues, I looked at other tools to eventually replace &lt;code&gt;telnet&lt;&#x2F;code&gt; with something better. I tried &lt;code&gt;nmap&lt;&#x2F;code&gt; which is also a port scanner, but is unreliable since a lot of hipster sysadmins drinking the security koolaid block port scanning tools like these. I wanted a dependable tooling and after a bit of Google-fu, I stumbled across &lt;code&gt;netcat&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;netcat&lt;&#x2F;code&gt; is basically a swiss army knife to perform all kind of ops with TCP&#x2F;UDP. You can create a file server, chat client&#x2F;server, TCP client etc. We are simply interested in the port scanning abilities of this for this blog post, so let’s actually see how to use it for the same.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;: Install &lt;code&gt;netcat-openbsd&lt;&#x2F;code&gt; as it is a rewritten version of &lt;code&gt;netcat-traditional&lt;&#x2F;code&gt; with some more bells and whistles.&lt;&#x2F;p&gt;
&lt;p&gt;The basic syntax for port scanning looks like:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;nc -z host port&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;-z&lt;&#x2F;code&gt; tells nc to not send any data, just &lt;em&gt;scan&lt;&#x2F;em&gt; for any process listening on the target port. This is much better (and faster) than &lt;code&gt;telnet&lt;&#x2F;code&gt; client initiating a connection with the upstream.&lt;&#x2F;p&gt;
&lt;p&gt;To make it more usable however, let’s pepper our command with some helpful flags:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;nc -vz -w 3 host port&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;-v&lt;&#x2F;code&gt; turns on verbose mode which outputs diagnostic messages. &lt;code&gt;-w&lt;&#x2F;code&gt; adds the timeout for the connection to be established. If you want to set a timeout in &lt;code&gt;telnet&lt;&#x2F;code&gt; there’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;questions&#x2F;224623&#x2F;telnet-command-with-custom-timeout-duration&quot;&gt;hack&lt;&#x2F;a&gt; for it.&lt;&#x2F;p&gt;
&lt;p&gt;You can even supply a range of ports to netcat like:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;nc -vz -w 3 host 8000-9000&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Quick Tip&lt;&#x2F;em&gt;: You can also give an alias for port instead of the number. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;nc&lt;&#x2F;span&gt;&lt;span&gt; -vz -w 3 google.com https&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; google.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 443&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; port&lt;&#x2F;span&gt;&lt;span&gt; [tcp&#x2F;https&lt;&#x2F;span&gt;&lt;span&gt;] succeeded&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;nc&lt;&#x2F;span&gt;&lt;span&gt; -vz -w 3 google.com ssh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nc:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; connect&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; google.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 22&lt;&#x2F;span&gt;&lt;span&gt; (tcp&lt;&#x2F;span&gt;&lt;span&gt;) timed out: Operation now in progress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nc:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; connect&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; google.com&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 22&lt;&#x2F;span&gt;&lt;span&gt; (tcp&lt;&#x2F;span&gt;&lt;span&gt;) failed: Network is unreachable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hope this post pretty much sums up the usage of netcat for port scanning! Read the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;1&#x2F;nc&quot;&gt;man page&lt;&#x2F;a&gt; for more info.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>kubectl wait</title>
        <published>2020-01-01T08:10:55+05:30</published>
        <updated>2020-01-01T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/kubectl-wait/"/>
        <id>https://mrkaran.dev/posts/kubectl-wait/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/kubectl-wait/">&lt;p&gt;For the longest time I’ve had these commands in my &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; file for a K8s CD pipeline:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kubectl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; overlays&#x2F;prod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;Waiting for 15 seconds for pods to be restarted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; sleep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 15&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kubectl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; po&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, basically I apply the changes to cluster using &lt;code&gt;kubectl apply&lt;&#x2F;code&gt; and wait for arbitary decided time (15 seconds) to see the pod &lt;code&gt;status&lt;&#x2F;code&gt;, hoping by that time the new deployments would have been active and old pods would be deleted. As the traditional SRE saying goes &lt;em&gt;Hope is not a strategy&lt;&#x2F;em&gt; this was clearly hacky and I knew it back then, just didn’t priortise enough to find a replacement. Recently got to know about &lt;code&gt;kubectl wait&lt;&#x2F;code&gt; and woah, this is exactly what I needed. I can wait till either the condition is true or a timeout happens, whichever is earlier. This is so much better than the previous &lt;em&gt;hack&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kubectl wait --for=condition=available --timeout=60s --all deployments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here the &lt;code&gt;condition&lt;&#x2F;code&gt; depends on the resource you are selecting. You can see the values for &lt;code&gt;Conditions&lt;&#x2F;code&gt; using &lt;code&gt;kubectl describe &amp;lt;resource&amp;gt;&lt;&#x2F;code&gt;. For eg, for deployment and pods:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; describe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; deployments&#x2F;{deployment_name}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Conditions&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Conditions:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;           Status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Reason&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  ----&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;           -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-----&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-----&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  Progressing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    True&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    NewReplicaSetAvailable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  Available&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      True&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    MinimumReplicasAvailable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; describe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pods&#x2F;{pod_name}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Conditions&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Conditions:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;              Status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  Initialized&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  Ready&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;             True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  ContainersReady&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  PodScheduled&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;      True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, now you’ll set the value for &lt;code&gt;condition&lt;&#x2F;code&gt; according to your choice. This will be pretty useful in CI&#x2F;CD pipelines. That’s pretty much it.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Unrelated, but I thought about doing more such &lt;em&gt;short&lt;&#x2F;em&gt; posts and be consistent with more of writing. If you liked the short and precise format or have any feedback on it, do reach out to me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;@mrkaran_&quot;&gt;Twitter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Happy New Year :)&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introducing kubekutr</title>
        <published>2019-12-30T08:10:55+05:30</published>
        <updated>2019-12-30T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/introducing-kubekutr/"/>
        <id>https://mrkaran.dev/posts/introducing-kubekutr/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/introducing-kubekutr/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;mr-karan&#x2F;kubekutr&#x2F;master&#x2F;logo.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;kubekutr&#x2F;&quot;&gt;kubekutr&lt;&#x2F;a&gt; was born out of my frustration of organising K8s resource manifests files&#x2F;directories. For the uninitiated, K8s lets you hold the state of your cluster &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;manage-kubernetes-objects&#x2F;declarative-config&#x2F;&quot;&gt;declaratively&lt;&#x2F;a&gt; as “manifest” files. K8s does so by a lot of asynchronous control loops to check whether the desired state matches the real world state and in case of drifts, it resets back to the user desired state (I oversimplified this, but hope you get the drift ;)). These files are predominantly &lt;code&gt;YAML&lt;&#x2F;code&gt; but there’s support for &lt;code&gt;JSON&lt;&#x2F;code&gt; as well. Anyway, to create these manifest files for a production level project is quite a bit of manual labour. The API spec of every resource in Kubernetes is quite &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;generated&#x2F;kubernetes-api&#x2F;v1.14&#x2F;&quot;&gt;daunting&lt;&#x2F;a&gt; and overwhelming. There are tools like Helm which abstract away the complexity of these YAML with it’s own templating system. There are quite a lot of these charts available for 3rd party apps &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;helm&#x2F;charts&quot;&gt;here&lt;&#x2F;a&gt;. The idea is you populate the Chart with just your own config “values” and you’ve a deployment ready in no time. Admittedly this works quite well for something you want to take out for a quick spin but personally I am not quite a fan of hiding away the complexity with a &lt;em&gt;magic&lt;&#x2F;em&gt; layer. Also, the problem with Helm was the “Chart” (and templates) still had to be written by someone if you have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes-sigs&#x2F;kustomize&#x2F;blob&#x2F;master&#x2F;docs&#x2F;glossary.md#bespoke-configuration&quot;&gt;bespoke&lt;&#x2F;a&gt; application. Helm is more geared towards common off the shelf apps like DBs, Key Value stores, web proxies etc.&lt;&#x2F;p&gt;
&lt;p&gt;I found out &lt;a href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;introducing-kubekutr&#x2F;github.com&#x2F;kubernetes-sigs&#x2F;kustomize&quot;&gt;kustomize&lt;&#x2F;a&gt; few months back and quite happy with it’s approach towards managing manifests. The basic idea behind &lt;code&gt;kustomize&lt;&#x2F;code&gt; is that you create a &lt;em&gt;base&lt;&#x2F;em&gt; and any kind of “customisations” must come as &lt;em&gt;overlays&lt;&#x2F;em&gt;. This is such a powerful technique over wrangling templates. &lt;code&gt;kustomize&lt;&#x2F;code&gt; A common approach is to name these &lt;em&gt;overlays&lt;&#x2F;em&gt; based on the environment. For example, &lt;code&gt;dev&lt;&#x2F;code&gt; deployment can have &lt;code&gt;replicas: 1&lt;&#x2F;code&gt; for a pod, but &lt;code&gt;prod&lt;&#x2F;code&gt; can apply a “patch” to update with &lt;code&gt;repliacs: 3&lt;&#x2F;code&gt;. This way of separating two environments helps a lot when you follow &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.weave.works&#x2F;technologies&#x2F;gitops&#x2F;&quot;&gt;GitOps&lt;&#x2F;a&gt; approach of deployment. All fine and good, until I realised I spent way too much time on copy-pasting the bases for different projects and manually editing these files for the new project config.&lt;&#x2F;p&gt;
&lt;p&gt;Then I did what any other programmer would do, spend some more time to automate :P And that is how &lt;code&gt;kubekutr&lt;&#x2F;code&gt; was born. (Quite an anticlimax I know!)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;kubekutr&lt;&#x2F;code&gt; is a really simple tool to bootstrap a Kustomize &lt;code&gt;base&lt;&#x2F;code&gt;. &lt;code&gt;kubekutr&lt;&#x2F;code&gt; reads a config file, templates out different resources and produces them as YAML files. Now, I know a lot of you reading this would be going &lt;em&gt;Another damn templating solution&lt;&#x2F;em&gt; in your mind and while that reaction is warranted, given that we have 200+ &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;spreadsheets&#x2F;d&#x2F;1FCgqz1Ci7_VCz_wdh8vBitZ3giBtac_H8SBw4uxnrsE&#x2F;edit#gid=0&quot;&gt;tools&lt;&#x2F;a&gt; in the community (everyone trying to solve similar problems in their own ways), I &lt;em&gt;legit&lt;&#x2F;em&gt; could not find a simple enough tool which would let the boring part of scaffolding a base out of my way and let me focus on what’s more important: the actual deployment. Hence I just decided to roll out my own solution which is the best one according to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;IKEA_effect&quot;&gt;IKEA effect&lt;&#x2F;a&gt; (&lt;em&gt;just kidding&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;workflow&quot;&gt;Workflow&lt;a class=&quot;zola-anchor&quot; href=&quot;#workflow&quot; aria-label=&quot;Anchor link for: workflow&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;So, let’s say you need to create a Nginx deployment, the &lt;code&gt;kubekutr&lt;&#x2F;code&gt; &lt;code&gt;config.yml&lt;&#x2F;code&gt; would look something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;deployments:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - name: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    replicas: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    labels:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - name: &amp;#39;service: nginx&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    containers:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - name: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        image: &amp;#39;nginx:latest&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        portInt: 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        portName: nginx-port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;services:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - name: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    type: ClusterIP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    port: 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    targetPort: 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    labels:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - name: &amp;#39;service: nginx&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    selectors:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - name: &amp;#39;service: nginx&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To create the &lt;code&gt;base&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;kubekutr -c config.yml scaffold -o nginx-deployment&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;nginx-deployment&lt;&#x2F;code&gt; folder is initialised and you can view &lt;code&gt;deployments&#x2F;nginx.yml&lt;&#x2F;code&gt; and &lt;code&gt;service&#x2F;nginx.yml&lt;&#x2F;code&gt; which &lt;code&gt;kubekutr&lt;&#x2F;code&gt; created.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ tree nginx-deployment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|-- base&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   |-- deployments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   |   `-- nginx.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   |-- ingresses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   |-- services&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   |   `-- nginx.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|   `-- statefulsets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cat base&#x2F;deployments&#x2F;nginx.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apiVersion: apps&#x2F;v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kind: Deployment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;metadata:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  labels:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    service: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;spec:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  replicas: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  selector:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    matchLabels:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      service: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  template:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    metadata:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      labels:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        service: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    spec:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      containers:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        - name: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          image: nginx:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          ports:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          - containerPort: 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            name: nginx-port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cat base&#x2F;services&#x2F;nginx.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apiVersion: v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kind: Service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;metadata:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  labels:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    service: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;spec:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ports:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - port: 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      targetPort: 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      protocol: TCP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type: ClusterIP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  selector:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    service: nginx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can now use the generated folder as a Kustomize &lt;code&gt;base&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;non-goals&quot;&gt;Non Goals&lt;a class=&quot;zola-anchor&quot; href=&quot;#non-goals&quot; aria-label=&quot;Anchor link for: non-goals&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;kubekutr&lt;&#x2F;code&gt; isn’t meant to replace the existing tools, it’s just a real simple cookie cutter approach to &lt;code&gt;kustomize&lt;&#x2F;code&gt; bases and that’s pretty much it. &lt;code&gt;kustomize&lt;&#x2F;code&gt; is native to Kubernetes and exposes the full API spec to end users. I feel that is much more better approach than templating solutions, the users must be exposed to the standard conventions rather than a random tool’s own config fields. The benefits are the same conventions can then be used across a wide variety of tools (like &lt;code&gt;kubekutr&lt;&#x2F;code&gt;) and users are in better control of the underlying resources. Adding a layer of magic also makes it harder to debug when shit goes down. Hence &lt;code&gt;kubekutr&lt;&#x2F;code&gt; chose &lt;code&gt;kustomize&lt;&#x2F;code&gt; to do all the heavy lifting of managing manifests.&lt;&#x2F;p&gt;
&lt;p&gt;There’s a lot of scope of improvements, but I wanted to just Ship It! and get some initial feedback. Let me know your thoughts on this :)&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A quick primer on dig</title>
        <published>2019-11-11T10:57:55+05:30</published>
        <updated>2019-11-11T10:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/dig-overview/"/>
        <id>https://mrkaran.dev/posts/dig-overview/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/dig-overview/">&lt;p&gt;Dig is a DNS lookup utility developed by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;BIND&quot;&gt;BIND&lt;&#x2F;a&gt; which helps a lot while troubleshooting DNS issues (which are more common than you probably think #hugops). I use &lt;code&gt;dig&lt;&#x2F;code&gt; fairly often and thought to write an introductory guide on how you can use &lt;code&gt;dig&lt;&#x2F;code&gt; with some practical examples that’ll help you &lt;code&gt;dig&lt;&#x2F;code&gt; through DNS issues faster (sorry for the lame pun, couldn’t resist.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basics&quot;&gt;Basics&lt;a class=&quot;zola-anchor&quot; href=&quot;#basics&quot; aria-label=&quot;Anchor link for: basics&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The most basic and common usage for &lt;code&gt;dig&lt;&#x2F;code&gt; is to query the authorative servers for a particular domain and retrieve the IP. If it’s an IPv4 then you should be looking at &lt;code&gt;A&lt;&#x2F;code&gt; record, while if it’s IPv6 then &lt;code&gt;AAAA&lt;&#x2F;code&gt; record is your friend. Let’s see the DNS records for the site you’re currently on:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;➜&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  ~&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #ADBAC7);&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; DiG&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9.10.6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #ADBAC7);&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; global options: +cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; Got answer:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 23292&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; OPT PSEUDOSECTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;; EDNS: version: 0, flags:; udp: 1220&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; QUESTION SECTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;mrkaran.dev.			IN	A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; ANSWER SECTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran.dev.		60	IN	A	206.189.89.118&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; Query time: 6 msec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; SERVER: 127.0.0.1#53(127.0.0.1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; WHEN: Tue Oct 29 23:13:31 IST 2019&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; MSG SIZE  rcvd: 67&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the most basic example for &lt;code&gt;dig&lt;&#x2F;code&gt;. Let’s explore some of the additional options.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;keep-it-short&quot;&gt;Keep it short&lt;a class=&quot;zola-anchor&quot; href=&quot;#keep-it-short&quot; aria-label=&quot;Anchor link for: keep-it-short&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;dig +short&lt;&#x2F;code&gt; keeps the information to bare minimum and only displays the &lt;code&gt;ANSWER&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +short&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;206.189.89.118&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;nameserver-details&quot;&gt;Nameserver details&lt;a class=&quot;zola-anchor&quot; href=&quot;#nameserver-details&quot; aria-label=&quot;Anchor link for: nameserver-details&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you want to find the &lt;code&gt;Nameserver&lt;&#x2F;code&gt; for your DNS records, you can use the query type &lt;code&gt;ns&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ns&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +short&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;alec.ns.cloudflare.com.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;cruz.ns.cloudflare.com.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;ns&lt;&#x2F;code&gt; is one of the many query types you can use to indicate which type of DNS record you want to fetch. Default is &lt;code&gt;A&lt;&#x2F;code&gt; record which returns the IPv4 address of the domain (unless it’s a root domain, in which case the default query type is &lt;code&gt;NS&lt;&#x2F;code&gt;). Some other examples of query types are &lt;code&gt;mx&lt;&#x2F;code&gt;, &lt;code&gt;AAAA&lt;&#x2F;code&gt;, &lt;code&gt;TXT&lt;&#x2F;code&gt; etc.&lt;&#x2F;p&gt;
&lt;p&gt;Fun Fact: &lt;code&gt;ANY&lt;&#x2F;code&gt; query type has become &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.cloudflare.com&#x2F;rfc8482-saying-goodbye-to-any&#x2F;&quot;&gt;obsolete&lt;&#x2F;a&gt; as per the new &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc8482&quot;&gt;RFC8482&lt;&#x2F;a&gt; and DNS operators can choose to not respond to this query. The reason for this is that the payload response size for an &lt;code&gt;ANY&lt;&#x2F;code&gt; query is quite huge (since it has to return all type of DNS records) and this could affect the performance of authoritative servers in case of a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.cloudflare.com&#x2F;deep-inside-a-dns-amplification-ddos-attack&#x2F;&quot;&gt;DNS amplification&lt;&#x2F;a&gt; attack.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-different-dns-server&quot;&gt;Using different DNS server&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-different-dns-server&quot; aria-label=&quot;Anchor link for: using-different-dns-server&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Let’s say you want to switch to a different resolver, you can use &lt;code&gt;@&lt;&#x2F;code&gt; followed by the address of your DNS server.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; @9.9.9.9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;reverse-dns-lookup&quot;&gt;Reverse DNS Lookup&lt;a class=&quot;zola-anchor&quot; href=&quot;#reverse-dns-lookup&quot; aria-label=&quot;Anchor link for: reverse-dns-lookup&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This one’s actually pretty cool. &lt;code&gt;dig -x&lt;&#x2F;code&gt; lets you query the IP and retrieve the hostname details for that IP.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 206.189.89.118&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;multiple-queries&quot;&gt;Multiple queries&lt;a class=&quot;zola-anchor&quot; href=&quot;#multiple-queries&quot; aria-label=&quot;Anchor link for: multiple-queries&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can input a list of domain names and pass the file with the arg &lt;code&gt;-f&lt;&#x2F;code&gt; to dig.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; digfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;mrkaran.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;joinmastodon.org&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;zoho.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To list down all MX records for the domains in a file, you can use something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; digfile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +noall&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +answer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;mrkaran.dev.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;		242&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mx.zoho.in.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;mrkaran.dev.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;		242&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	20&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mx2.zoho.in.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;mrkaran.dev.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;		242&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	50&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mx3.zoho.in.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;joinmastodon.org.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	21599&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; in1-smtp.messagingengine.com.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;joinmastodon.org.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	21599&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	20&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; in2-smtp.messagingengine.com.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;zoho.com.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;		299&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; smtpin.zoho.com.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;zoho.com.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;		299&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	20&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; smtpin2.zoho.com.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;zoho.com.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;		299&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	IN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;	MX&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;	50&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; smtpin3.zoho.com.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;search-list&quot;&gt;Search List&lt;a class=&quot;zola-anchor&quot; href=&quot;#search-list&quot; aria-label=&quot;Anchor link for: search-list&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I learnt this recently while debugging a DNS issue in one of the Kubernetes pods. Dig doesn’t use search paths by default, so if you have a service say &lt;code&gt;redis&lt;&#x2F;code&gt; inside a namespace dig won’t fetch any result:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +short&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; empty output, indicates no record found&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is because a service name in Kubernetes is of the form &lt;code&gt;service.namespace.svc.cluster.local&lt;&#x2F;code&gt;. So, we should actually be querying for &lt;code&gt;redis.myns.svc.cluster.local&lt;&#x2F;code&gt; and we’ll get our result. But isn’t that too long and painful (sorry for the pun) to type?&lt;&#x2F;p&gt;
&lt;p&gt;So, there’s another option &lt;code&gt;+search&lt;&#x2F;code&gt; which can be used to find all domains matching the search path defined in &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; namesever configurations.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;resolv.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;nameserver&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.100.0.10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;search&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; myns.svc.cluster.local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; svc.cluster.local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cluster.local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now query for &lt;code&gt;redis&lt;&#x2F;code&gt; with this search list:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +search&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +short&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;10.100.32.73&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;dnssec-validation&quot;&gt;DNSSec Validation&lt;a class=&quot;zola-anchor&quot; href=&quot;#dnssec-validation&quot; aria-label=&quot;Anchor link for: dnssec-validation&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;dig&lt;&#x2F;code&gt; even lets you validate the DNS records you received using &lt;code&gt;DNSSEC&lt;&#x2F;code&gt; validation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +dnssec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #ADBAC7);&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; DiG&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9.10.6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #ADBAC7);&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +dnssec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; global options: +cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; Got answer:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 36275&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; OPT PSEUDOSECTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;; EDNS: version: 0, flags: do; udp: 1452&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; QUESTION SECTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;mrkaran.dev.			IN	A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; ANSWER SECTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran.dev.		20	IN	A	178.128.17.49&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;mrkaran.dev.		20	IN	RRSIG	A 13 2 20 20191112173050 20191110153050 34505 mrkaran.dev. Tl3zD6EqfVRvZi79ahePQcAXnbSUY9ZEYx&#x2F;KwXnDUyonlrCKuBHzIYYC MJoVns410+sOwbIrcAdLgx+eiMYqRQ==&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; Query time: 65 msec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; SERVER: 1.1.1.1#53(1.1.1.1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; WHEN: Mon Nov 11 22:01:01 IST 2019&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; MSG SIZE  rcvd: 163&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The important bit to note here is the &lt;code&gt;ad&lt;&#x2F;code&gt; flag set which represents Authenticated Data. The records will only be returned if the validation succeeds (unless you also specify &lt;code&gt;+cd&lt;&#x2F;code&gt; which indicates Checking Disabled flag.)&lt;&#x2F;p&gt;
&lt;p&gt;On a server which doesn’t have DNSSEC enabled, you can see no records are returned with the &lt;code&gt;+dnssec&lt;&#x2F;code&gt; flag.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dnssec-failed.org&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +dnssec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #ADBAC7);&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; DiG&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9.10.6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #ADBAC7);&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; dnssec-failed.org&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; +dnssec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; global options: +cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; Got answer:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: SERVFAIL, id: 19886&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; QUESTION SECTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;dnssec-failed.org.		IN	A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; Query time: 335 msec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; SERVER: 1.1.1.1#53(1.1.1.1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; WHEN: Mon Nov 11 22:03:50 IST 2019&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;;; MSG SIZE  rcvd: 35&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That pretty much broadly covers some practical examples with &lt;code&gt;dig&lt;&#x2F;code&gt;. I will soon write a detailed post on how &lt;code&gt;DNSSEC&lt;&#x2F;code&gt; validation works and why it needs to be mainstream.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>GitOps approach to Continuous Delivery for Kubernetes</title>
        <published>2019-11-11T10:57:55+05:30</published>
        <updated>2019-11-11T10:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/gitops-kubernetes/"/>
        <id>https://mrkaran.dev/posts/gitops-kubernetes/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/gitops-kubernetes/">&lt;p&gt;In this post, I’d like to share my experience and learnings about configuring a deployment pipeline for Kubernetes. I’ll be using Gitlab CI&#x2F;CD and AWS EKS to demonstrate the concept, but the core idea remains the same: &lt;em&gt;all changes must come declaratively from a single source of truth&lt;&#x2F;em&gt;. &lt;code&gt;GitOps&lt;&#x2F;code&gt; is a relatively newer term in the town but goes back to the fundamentals of &lt;em&gt;Infra as Code&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;GitOps fundamentally is an operating model to perform tasks on Kubernetes related to deployments, configuration, secrets and monitoring workloads. All kind of changes must be performed via a single place, which happens to be a &lt;code&gt;git&lt;&#x2F;code&gt; repo. Benefits of that are what basically benefits of version controlling the code is. So why treat infra as any different? &lt;code&gt;git&lt;&#x2F;code&gt; happens to be the single source of truth for your infra, rollbacks are easy as reverting to last known good configuration and every change can be observed&#x2F;verified.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;a class=&quot;zola-anchor&quot; href=&quot;#goals&quot; aria-label=&quot;Anchor link for: goals&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of tutorials&#x2F;blog posts hitherto cover a very basic scenario where they do &lt;code&gt;kubectl apply&lt;&#x2F;code&gt; and voila the deployment’s live. However we all know things are very different (to say the least) in production, so this post will cover all aspects of deployment:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Creating Manifests&lt;&#x2F;li&gt;
&lt;li&gt;Environment Promotion&lt;&#x2F;li&gt;
&lt;li&gt;Handling config and secrets&lt;&#x2F;li&gt;
&lt;li&gt;Authorization of CI&#x2F;CD in the cluster&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;basics&quot;&gt;Basics&lt;a class=&quot;zola-anchor&quot; href=&quot;#basics&quot; aria-label=&quot;Anchor link for: basics&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A GitOps workflow looks like:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;push-vs-pull&quot;&gt;Push vs Pull&lt;a class=&quot;zola-anchor&quot; href=&quot;#push-vs-pull&quot; aria-label=&quot;Anchor link for: push-vs-pull&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;There are 2 approaches to how you can handle deployments to a cluster. In a Pull based approach, the cluster runs a synch controller program which continmioously syncs the state of cluster with a Git repo. Any changes you make to the Git repo will be synced automatically in cluster. The idea is that there should be no drift in the desired state via Git repo and the actual state of cluster. Flux, Argo are good tools if you want a Pull based pipeline. The merits of Pull based pipeline is it’s more secure, since the deployment is actually happening inside cluster and no external sytstem needs to communicate to your production infra. The demerits are sometimes you’ve to wait for the changes to be synced (every controller runs these sync process in a loop with a sleep which can be configured). Also using any kind of preprocessing tools like Kustomize becomes difficult, since Flux just syncs the state and applies those changes. Handling of secrets is yet another concern, you need to look . And finally GitOps is a relatively newer tech in market so GitOps tooling is still nascent and like with any other relatively (non battle tested) software you’re gonna find bugs.&lt;&#x2F;p&gt;
&lt;p&gt;Push Approach however is a traditional CD approach, where the CD server talks to the cluster and applies changes through commands. In context of normal EC2 deployments, those commands could be SSH into server, running ansible playbook etc. In context of K8s however &lt;code&gt;kubectl&lt;&#x2F;code&gt; does the magic for us. The CD server needs to talk to the K8s API server and run kubectl commands to change the cluster state.
The merits of this approach are you can run all sorts of commands inside deployment pipeline and make it fully customisable. Handling of secrets also can be handled natively (like Gitlab env variables) or encrypted in &lt;code&gt;git&lt;&#x2F;code&gt;.
The demerits is that your production cluster is now exposed to your CD server.&lt;&#x2F;p&gt;
&lt;p&gt;Overall, if you have an airgapped CD server with no inbound ports open, access controll the user auth to CD, I found the Push approach to be more preferable. YMMV.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-the-pipeline&quot;&gt;Writing the pipeline&lt;a class=&quot;zola-anchor&quot; href=&quot;#writing-the-pipeline&quot; aria-label=&quot;Anchor link for: writing-the-pipeline&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve created a docker &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;eks-gitops&quot;&gt;image&lt;&#x2F;a&gt; &lt;code&gt;eks-gitops&lt;&#x2F;code&gt; which I’ll be using throughout the pipeline. This container image contains popular tools like &lt;code&gt;kustomize&lt;&#x2F;code&gt;, &lt;code&gt;kubeval&lt;&#x2F;code&gt; etc and scripts to configure access to cluster using &lt;code&gt;kubectl&lt;&#x2F;code&gt; using &lt;code&gt;aws-iam-authenticator&lt;&#x2F;code&gt;. I’ve written more about how RBAC works inside EKS &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;intro-rbac-kubernetes&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Excerpt from &lt;code&gt;.gitla-ci.yml&lt;&#x2F;code&gt;&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Use this as base image for all jobs unless overriden&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;efault&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rkaran&#x2F;eks-gitops:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ntrypoint&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;## Pipeline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tages&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;alidate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;prepare-the-manifests&quot;&gt;Prepare the manifests&lt;a class=&quot;zola-anchor&quot; href=&quot;#prepare-the-manifests&quot; aria-label=&quot;Anchor link for: prepare-the-manifests&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I use &lt;code&gt;Kustomize&lt;&#x2F;code&gt; to prepare the manifests. Advantage of &lt;code&gt;Kustomize&lt;&#x2F;code&gt; is writing template free YAMLs but still be able to customise them heavily using overlays. For different environments, you can apply certain changes like increasing resource requests, adding more storage, while keeping the base same.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s a folder structure (from a real GitOps repo) I follow for manifests:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; base&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; deployments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; app.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; celery.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nginx.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ingresses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; web.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kustomization.yaml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; services&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; app.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nginx.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis-headless.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; statefulsets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; volumes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; redis.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kubekutter.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Makefile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; overlays&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; prod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; configs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; app-config.env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; app-nginx.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kustomization.env.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; namespace.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; patches&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; configure-configmap-volume.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ├──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; modify-alb.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     │  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; resource-limits.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;│  &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     └──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rbac.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;└──&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; README.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Shameless Plug&lt;&#x2F;strong&gt;: I created &lt;code&gt;kubekutr&lt;&#x2F;code&gt; which makes managing of these manifests using &lt;code&gt;kustomize&lt;&#x2F;code&gt; a breeze.&lt;&#x2F;p&gt;
&lt;p&gt;Some things to note here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Inside &lt;code&gt;base&#x2F;&lt;&#x2F;code&gt;, I keep all the &lt;code&gt;base&lt;&#x2F;code&gt; resources required for the app to run. The resources can be &lt;code&gt;Service&lt;&#x2F;code&gt;, &lt;code&gt;Deployment&lt;&#x2F;code&gt;, &lt;code&gt;Ingress&lt;&#x2F;code&gt; etc.&lt;&#x2F;li&gt;
&lt;li&gt;Inside &lt;code&gt;overlays&lt;&#x2F;code&gt; there are multiple folders for different environment. This is very crucial as we want to separate the production config with a UAT config. Last-mile configuration to the base becomes very easy with this folder structure, since you only now need to build the manifests by targetting a specific folder in CI.&lt;&#x2F;li&gt;
&lt;li&gt;Inside &lt;code&gt;overlays&#x2F;{env}&#x2F;patches&lt;&#x2F;code&gt; are all the “patches” you want to do to the base resource. Think like replica count, ALB subnets (since different env can be in different VPCs), increasing resource limits and stuff like that.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;rbac.yml&lt;&#x2F;code&gt; abd &lt;code&gt;namespace.yml&lt;&#x2F;code&gt; is the only missing piece because it’s like a chicken and egg problem. I cannot deploy directly (at first go) from a CI&#x2F;CD if I don’t have a namespace created since the CD server is configured only has limited namespaced restricted access. So unless I create a namespace, add proper RBAC for the CD server I cannot do any deployments from CD. Note however this is only a first time step, which I guess is okay.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;lint-yo-manifest&quot;&gt;Lint yo manifest&lt;a class=&quot;zola-anchor&quot; href=&quot;#lint-yo-manifest&quot; aria-label=&quot;Anchor link for: lint-yo-manifest&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I’m using &lt;code&gt;kubeval&lt;&#x2F;code&gt; to lint the manifests. The manifests have to prepared by &lt;code&gt;kustomize&lt;&#x2F;code&gt;. &lt;code&gt;CI_ENVIRONMENT_NAME&lt;&#x2F;code&gt; is set by &lt;code&gt;Gitlab&lt;&#x2F;code&gt; when you specify an environment for a job. Don’t sweat about this part, I’ll describe it more as we proceed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Validate the yaml using kubeval&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lint&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;xtends&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;prepare-manifest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;alidate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;cript&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;cho &amp;quot;Linting manifest for ${CI_ENVIRONMENT_NAME}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ustomize build overlays&#x2F;$CI_ENVIRONMENT_NAME --load_restrictor none | kubeval&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;setup-environment&quot;&gt;Setup environment&lt;a class=&quot;zola-anchor&quot; href=&quot;#setup-environment&quot; aria-label=&quot;Anchor link for: setup-environment&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can define environment name as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Create an environment to record all jobs for this env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;prod&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;prod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;rod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ttps:&#x2F;&#x2F;prod.site&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;dev&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ttps:&#x2F;&#x2F;dev.site&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Any job which is to be executed in a particular environment can include this variable and &lt;code&gt;CI_ENVIRONMENT_NAME&lt;&#x2F;code&gt; will be automatically set.&lt;&#x2F;p&gt;
&lt;p&gt;A cool feature of Gitlab is that you can restrict Variables scoped to the environment they are defined in.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configure-secrets&quot;&gt;Configure Secrets&lt;a class=&quot;zola-anchor&quot; href=&quot;#configure-secrets&quot; aria-label=&quot;Anchor link for: configure-secrets&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;All secrets are defined as Environment Variables in Gitlab CD pipeline. While running the job, the runner has access to these variables and with the help of &lt;code&gt;secretGenerator&lt;&#x2F;code&gt; in &lt;code&gt;kustomize&lt;&#x2F;code&gt;, the &lt;code&gt;Secret&lt;&#x2F;code&gt; is created.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;code&gt;secretGenerator&lt;&#x2F;code&gt; because any time a K8s secret changes, kustomize appends with a new suffix, which makes the Replication Controller believe that they deployment has changed. So a new deployment is automatically triggered.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;authenticate-to-cluster&quot;&gt;Authenticate to cluster&lt;a class=&quot;zola-anchor&quot; href=&quot;#authenticate-to-cluster&quot; aria-label=&quot;Anchor link for: authenticate-to-cluster&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;EKS uses aws-iam-authenticator and uses IAM access roles to allow the cluster to perform actions. Since this is a push based pipeline, you need to allow the access from your CD server to port 443.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deploy-changes&quot;&gt;Deploy changes&lt;a class=&quot;zola-anchor&quot; href=&quot;#deploy-changes&quot; aria-label=&quot;Anchor link for: deploy-changes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is as simple as &lt;code&gt;kubectl apply&lt;&#x2F;code&gt; which configures all the changes and diff between cluster and real world state.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s a full gitops repo if you’re interested in checking it out:&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Intro to RBAC in EKS</title>
        <published>2019-11-01T18:10:55+05:30</published>
        <updated>2019-11-01T18:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/intro-rbac-kubernetes/"/>
        <id>https://mrkaran.dev/posts/intro-rbac-kubernetes/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/intro-rbac-kubernetes/">&lt;p&gt;EKS uses a custom authenticator tool called “aws-iam-authenticator”. The basic idea is to make the auth flow in EKS easier by using the tools you already use in AWS.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;images&#x2F;eks-iam.png&quot; alt=&quot;eks-auth&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To wrap your head around the flow, consider three separate entities:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A kubernetes resource (entire namespace, specific pods&#x2F;configs etc)&lt;&#x2F;li&gt;
&lt;li&gt;An action (get, watch, list, create, delete etc)&lt;&#x2F;li&gt;
&lt;li&gt;An IAM role&#x2F;user created on AWS&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Your usecase might be to give an IAM role access to a Kubernetes namespace for example with certain restricted actions.&lt;&#x2F;p&gt;
&lt;p&gt;Since K8s is basically client-server communication with the API server, we must need to perform the following two things for every single API request which goes to the control plane:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Authentication&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;kubectl&lt;&#x2F;code&gt; talks to the API server using the token generated by &lt;code&gt;aws-iam-authenticator&lt;&#x2F;code&gt;. The API server passes on this info to the AWS servers which validated if the originating call is coming from a valid IAM user or not. If not, the access is denied from K8s.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Authorization&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Once the IAM user is validated, the IAM user needs to be mapped to a user to perform Authorization so K8s API server can know whether the action&#x2F;resource requested for is to be allowed or not. This is where the &lt;code&gt;aws-auth-cm.yml&lt;&#x2F;code&gt; comes into the picture. It is basically a map of all IAM users with internal K8s groups or users created. The roles are assosciated to these users&#x2F;groups so once the mapping is done, K8s API server can know what to do with the API request.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-does-eks-know-my-iam&quot;&gt;How does EKS know my IAM?&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-does-eks-know-my-iam&quot; aria-label=&quot;Anchor link for: how-does-eks-know-my-iam&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you configured your &lt;code&gt;KUBECONFIG&lt;&#x2F;code&gt; correctly using &lt;code&gt;aws eks update-kubeconfig&lt;&#x2F;code&gt; then you’ll find the below lines in your config file. This basically runs a &lt;code&gt;aws cli&lt;&#x2F;code&gt; command to find your IAM user&#x2F;role configured on your system to produce a token.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   exec:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apiVersion: client.authentication.k8s.io&#x2F;v1alpha1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      args:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - -i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      - eks-zero-public&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      command: aws-iam-authenticator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;show-me-the-yaml-already&quot;&gt;Show me the YAML already&lt;a class=&quot;zola-anchor&quot; href=&quot;#show-me-the-yaml-already&quot; aria-label=&quot;Anchor link for: show-me-the-yaml-already&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;To create a Role and RoleBinding&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apiVersion: rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kind: Role&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;metadata:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  namespace: coolapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name: fullaccess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rules:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- apiGroups: [&amp;quot;&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  resources: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  verbs: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- apiGroups: [&amp;quot;apps&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  resources: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  verbs: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- apiGroups: [&amp;quot;batch&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  resources: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  verbs: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- apiGroups: [&amp;quot;extensions&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  resources: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  verbs: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- apiGroups: [&amp;quot;autoscaling&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  resources: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  verbs: [&amp;quot;*&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kind: RoleBinding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apiVersion: rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;metadata:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name: 10xdevs-fullaccess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  namespace: coolapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;subjects:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- kind: Group&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name: 10xdevs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  namespace: coolapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;roleRef:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  kind: Role&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name: fullaccess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apiGroup: rbac.authorization.k8s.io&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, for all the normal folks who don’t grok YAML as fast as 10x devops engineers, I am basically creating a Role &lt;code&gt;fullaccess&lt;&#x2F;code&gt; with all permissions for a namespace &lt;code&gt;coolapp&lt;&#x2F;code&gt; (innovative, ikr). Then I am &lt;code&gt;binding&lt;&#x2F;code&gt; this Role to a Group called &lt;code&gt;10xdevs&lt;&#x2F;code&gt; so that the group is allocated the role which has permissions. We will use this group &lt;code&gt;10xdevs&lt;&#x2F;code&gt; to map our AWS user now.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;To create the map of IAM Role&#x2F;User ARN with the above Role&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Edit your &lt;code&gt;aws-auth-cm.yml&lt;&#x2F;code&gt; and add the below stuff:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apiVersion: v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;kind: ConfigMap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;metadata:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name: aws-auth&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  namespace: kube-system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mapRoles ... &amp;lt;skipping&amp;gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mapUsers: |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - userarn: arn:aws:iam::&amp;lt;account-id&amp;gt;:user&#x2F;&amp;lt;user-name&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      username: 10xdevs-fullaccess # RoleBinding name created in previous step&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      groups:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        - 10xdevs # Group name created in previous step&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;verify-it-yourself&quot;&gt;Verify it yourself&lt;a class=&quot;zola-anchor&quot; href=&quot;#verify-it-yourself&quot; aria-label=&quot;Anchor link for: verify-it-yourself&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;kubectl auth can-i create pods --all-namespaces&lt;&#x2F;code&gt;: &lt;em&gt;should fail&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;kubectl auth can-i create pods -n coolapp&lt;&#x2F;code&gt;: &lt;em&gt;should work&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Kubernetes cluster on RPi</title>
        <published>2019-09-22T08:10:55+05:30</published>
        <updated>2019-09-22T08:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/home-server-setup/"/>
        <id>https://mrkaran.dev/posts/home-server-setup/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/home-server-setup/">&lt;p&gt;So, I got hold of 2 Raspberry Pi4 (still limited stocks in India) recently and wanted to build a Kubernetes cluster. Don’t ask why cause that would be pointless. I’ve little experience with a managed Kubernetes workload (Amazon EKS, which btw deserves its post 😝) but never really played around any of the K8s internal stuff yet. In this post, I’ll show you how I got a lightweight Kubernetes distro: K3s up and running.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;k3s.io&#x2F;&quot;&gt;k3s&lt;&#x2F;a&gt; is a pretty great Kubernetes distro which passes the K8s Conformance tests. On ARM architectures, you’re pretty much resource-bounded and you want the resource footprint of your infra to be as minimal as possible. In k3s there are a few changes such as the persistent layer of K8s is replaced with SQLite instead of etcd, unusable (legacy&#x2F;alpha) features of K8s are removed and cloud-provider plugins are not bundled (but can be installed separately). All of this together means just 40MB of a binary to run the cluster and ~250MB of memory usage on an idle cluster. Awesome, team &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;rancher.com&quot;&gt;Rancher&lt;&#x2F;a&gt; :)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;k3s-htop.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Automation is the key and even though I have just 2 nodes on RPi, I &lt;em&gt;Ansible-ized&lt;&#x2F;em&gt; the setup which I am hoping would save time in future if I add more nodes to the setup.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;a class=&quot;zola-anchor&quot; href=&quot;#hardware&quot; aria-label=&quot;Anchor link for: hardware&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;1x &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.crazypi.com&#x2F;raspberry-pi-products&#x2F;raspberry-pi-latest-model-boards&#x2F;raspberry-pi-4-4gb-india&quot;&gt;RPi4 4GB&lt;&#x2F;a&gt; and 1x &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.crazypi.com&#x2F;raspberry-pi-products&#x2F;raspberry-pi-latest-model-boards&#x2F;raspberry-pi-4-2gb-india&quot;&gt;RPi4 2GB&lt;&#x2F;a&gt; variant&lt;&#x2F;li&gt;
&lt;li&gt;2x &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;gp&#x2F;product&#x2F;B06Y63B51W&#x2F;ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&amp;amp;psc=1&quot;&gt;Samsung EVO micro SD Card&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;2x &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;gp&#x2F;product&#x2F;B01GGKYKQM&#x2F;ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&amp;amp;psc=1&quot;&gt;USBC Cables&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;1x &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;gp&#x2F;product&#x2F;B00P933OJC&#x2F;ref=ppx_yo_dt_b_asin_title_o06_s01?ie=UTF8&amp;amp;psc=1&quot;&gt;Amker Power Port&lt;&#x2F;a&gt; (don’t compromise on the power supply, give enough juice so RPi doesn’t throttle)&lt;&#x2F;li&gt;
&lt;li&gt;1x &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;gp&#x2F;product&#x2F;9800359788&#x2F;ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&amp;amp;psc=1&quot;&gt;TP-Link Network Switch&lt;&#x2F;a&gt; (my router has only 1 usable LAN port)&lt;&#x2F;li&gt;
&lt;li&gt;2x &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;gp&#x2F;product&#x2F;B00GZLJ3EM&#x2F;ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&amp;amp;psc=1&quot;&gt;CAT5 LAN cables&lt;&#x2F;a&gt; (keeping it basic, you can get fancy flat LAN cables if you wish to)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is how the final setup looks like:&lt;&#x2F;p&gt;
&lt;p&gt;{{&amp;lt; tweet 1175659256764219392 &amp;gt;}}&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-rpi&quot;&gt;Setting up RPi&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-rpi&quot; aria-label=&quot;Anchor link for: setting-up-rpi&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I downloaded &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.raspberrypi.org&#x2F;downloads&#x2F;raspbian&#x2F;&quot;&gt;Raspbian Buster Lite&lt;&#x2F;a&gt; because it’s the easiest to setup. Next step is to flash the SD card and for that, I used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.balena.io&#x2F;etcher&#x2F;&quot;&gt;Etcher&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;etcher.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To enable SSH access, you need to create an empty file &lt;code&gt;ssh&lt;&#x2F;code&gt; in the root volume.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; touch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;boot&#x2F;ssh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once all sorted, we can use Ansible to set up the basic OS stuff, like changing the default password, enabling password-less SSH login, timezone &amp;amp; locale settings, changing hostname etc. I’ll be sharing relevant Ansible snippets, if interested you can check out the complete playbook at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;hydra&quot;&gt;mr-karan&#x2F;hydra repo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We need to enable container features on the RPi so that &lt;code&gt;containerd&lt;&#x2F;code&gt; can run. Containers like Docker make use of &lt;code&gt;cgroups&lt;&#x2F;code&gt; (Linux kernel feature) which allows them to put resource limits on container processes like CPU and Memory. To enable &lt;code&gt;cgroups&lt;&#x2F;code&gt;, you need to edit &lt;code&gt;&#x2F;boot&#x2F;cmdline.txt&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;dd cgroup directives to boot command line config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ineinfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;boot&#x2F;cmdline.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;egexp&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;((.)+?)(\scgroup_\w+=\w+)*$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ine&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;\1 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ackrefs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Quick Tip: If you’re going to use RPi as a headless server (not connecting with any monitor) you can reduce the GPU Memory to lowest possible (16M)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;et GPU memory split to 16 MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ineinfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;boot&#x2F;config.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ine&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;gpu_mem=16&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;reate&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;deploy-k3s-cluster&quot;&gt;Deploy K3s cluster&lt;a class=&quot;zola-anchor&quot; href=&quot;#deploy-k3s-cluster&quot; aria-label=&quot;Anchor link for: deploy-k3s-cluster&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Next, we’ll come to the actual stuff, where we’ll download K3s binary and run as a systemd service. There’s a handy &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rancher&#x2F;k3s#quick-start---install-script&quot;&gt;shell script&lt;&#x2F;a&gt; to bootstrap the cluster provided by the Rancher team which setups the whole thing in one command. But if you wanna learn&#x2F;play around I’d recommend you do things the hard way (it’s not all that hard tho. ((twss!)).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ownload k3s binary armhf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;et_url&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ttps:&#x2F;&#x2F;github.com&#x2F;rancher&#x2F;k3s&#x2F;releases&#x2F;download&#x2F;{{ k3s_version }}&#x2F;k3s-armhf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;est&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;usr&#x2F;local&#x2F;bin&#x2F;k3s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;wner&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;oot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;roup&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;oot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 755&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hen&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ansible_facts.architecture is search(&amp;quot;arm&amp;quot;) )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ansible_facts.userspace_bits == &amp;quot;32&amp;quot; )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On the worker node, the process is similar, except you have to run the K3s with &lt;code&gt;agent&lt;&#x2F;code&gt; compared to &lt;code&gt;server&lt;&#x2F;code&gt; argument in the control plane. Things get a bit interesting here though. You need to give the cluster server URL along with it’s token in the command. A unique token is generated by the server at (&lt;code&gt;&#x2F;var&#x2F;lib&#x2F;rancher&#x2F;k3s&#x2F;server&#x2F;node-token&lt;&#x2F;code&gt;) which is used to join the worker nodes.&lt;&#x2F;p&gt;
&lt;p&gt;I did a bit of google-fu and got to know about this neat little Ansible module &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.ansible.com&#x2F;ansible&#x2F;latest&#x2F;modules&#x2F;set_fact_module.html&quot;&gt;&lt;code&gt;set_fact&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which lets you “store” a variable from one host and use it in a second host. Every Ansible host maintains a Python dict of “host facts”. In the second node, I access the cluster’s host fact &lt;code&gt;dict&lt;&#x2F;code&gt;, fetch the variable and use it in its systemd service template. Neat, ain’t it? Ansible has so many modules, it is mind-boggling.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Reading and storing the variable as a “host” fact&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; on the cluster&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ead node-token from control node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;lurp&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;var&#x2F;lib&#x2F;rancher&#x2F;k3s&#x2F;server&#x2F;node-token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;egister&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ode_token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;tore control node-token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;et_fact&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;3s_cluster_token&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ node_token.content | b64decode | regex_replace(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;, &amp;#39;&amp;#39;) }}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Using the variable from the server host, in a template on the agent host&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; on the agent (vars.yml)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;3s_server_address&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ hostvars[groups[&amp;#39;control&amp;#39;][0]].k3s_server_address }}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;3s_cluster_token&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{ hostvars[groups[&amp;#39;control&amp;#39;][0]].k3s_cluster_token }}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; use the value in a template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ervice&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;xecStart=&#x2F;usr&#x2F;local&#x2F;bin&#x2F;k3s agent --server {{ k3s_server_address }} --token {{ k3s_cluster_token }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;P.S. Shoutout to Ansible tho. It is one of my fav infra tooling available out there. It has some gotchas that you need to be aware of but by and large, the experience has been quite pleasant.&lt;&#x2F;p&gt;
&lt;p&gt;On the cluster, you should be able to see the nodes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kube-nodes.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;media3.giphy.com&#x2F;media&#x2F;5GoVLqeAOo6PK&#x2F;giphy.gif?cid=790b7611e1db0c17c4edaa597551fe748d1f3131429f424b&amp;amp;rid=giphy.gif&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;team-selfhost&quot;&gt;Team #SelfHost&lt;a class=&quot;zola-anchor&quot; href=&quot;#team-selfhost&quot; aria-label=&quot;Anchor link for: team-selfhost&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I am planning to host Bitwarden, Gitea and a Nextcloud instance on this cluster. Also will be using this as a testbed to play around with K8s internals. Stay tuned as I explore more of this!&lt;&#x2F;p&gt;
&lt;p&gt;Cheers! :)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My Personal Networking Setup</title>
        <published>2019-06-29T18:10:55+05:30</published>
        <updated>2019-06-29T18:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/personal-networking-setup/"/>
        <id>https://mrkaran.dev/posts/personal-networking-setup/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/personal-networking-setup/">&lt;blockquote&gt;
&lt;p&gt;If I have nothing to hide then I have nothing to show either&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;When you visit a site from your browser, there are several entities which have access to this information in one request-response cycle. Starting from the router you connect to, to the DNS resolver you use to resolve the IP Address of the site, and finally, the ISP which has access to the raw network packets (unencrypted or encrypted). They are all insecure by default and most users on the internet do not care about their privacy. ISPs can very easily profile you by the queries you do and sell that data to 3rd party Ad companies. There are still a huge number of sites on the world wide web which don’t have a basic SSL encryption turned on. Even with the HTTPS turned on your ISPs can simply see the unencrypted DNS queries and figure out the site you’re visiting. Browser fingerprinting is another well-known technique where you can be easily profiled based on the different parameters exposed by your browser and generate patterns in your browsing habits.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re a human you already care about your privacy. You won’t give out your Whatsapp chats to a random stranger on the streets to read, you won’t leave the door open while bathing, you won’t leave your credit card details out in the open, you will have a closed private discussion with your second half. Everyone does care about privacy in real life and everyone should care about the same online too.&lt;&#x2F;p&gt;
&lt;p&gt;“Some” social media companies exist solely on the data you provide. They are in the business of selling data and they don’t care a bit about your privacy. Every ad company out there wants an online persona about you, to feed you “personalized” recommendations. You may argue that they are “useful” but you cannot deny the fact that they are invading your privacy. You won’t like unwanted relationship advice from your neighbour when he hears you both fighting in the middle of the night. No one likes invaders, period.&lt;&#x2F;p&gt;
&lt;p&gt;Correlation of data points is easy to do in this age of ML&#x2F;AI (&lt;em&gt;Malai&lt;&#x2F;em&gt;). Re-iterating an example I read somewhere on the interwebz, say you search for a very generic term “cancer”, this alone doesn’t indicate that you have cancer but merely is suggestive of the fact that you are interested in knowing more about the disease. Now maybe a few days later you search for the phrase “buy a wig online”. These 2 search queries put together &lt;em&gt;can suggest&lt;&#x2F;em&gt; that you’ve had chemotherapy done recently. This is a piece of information you &lt;em&gt;might&lt;&#x2F;em&gt; not want to hide, but you do want to &lt;strong&gt;have an option&lt;&#x2F;strong&gt; right?&lt;&#x2F;p&gt;
&lt;p&gt;That’s the whole fight against companies which invade your privacy is. You have absolutely no choice. You’re devoid of any choice.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Google is your friend&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;You may not even realise but we’ve all been guilty of &lt;em&gt;Googling&lt;&#x2F;em&gt; some random shit for fun, googling about anxiety or depression when feeling low, how to lose weight and all such seemingly embarrassing questions and we simply confront these things to Google thinking that no one is spying on us or being judgemental of us and we’re in a safe zone. What if this “friend” is the one who’s stabbing your back. No surprises there! You don’t even know but these search engines might have already shared all such queries with several 3rd party providers and business who are on the lookout for such data.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I am scared&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I hope by now you’re convinced that you want some basic privacy online. If not, stop reading here because if this didn’t persuade you enough, nothing will and the rest of the blog is pretty useless for you anyway, so thanks for stopping by!&lt;&#x2F;p&gt;
&lt;p&gt;For the rest of us folks, there are a few practical things we can immediately start which. These are the things which have very less involvement of effort but are a good kickstart.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Use DNS over HTTPS (DoH) based resolver (personal choice: 1.1.1.1)&lt;&#x2F;li&gt;
&lt;li&gt;Use a browser which doesn’t ship with its own &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discourse.pi-hole.net&#x2F;t&#x2F;disable-async-dns-resolver-in-google-chrome&#x2F;9500&quot;&gt;god damn resolver&lt;&#x2F;a&gt; (personal choice: Firefox)&lt;&#x2F;li&gt;
&lt;li&gt;Use an Ad-Blocker (personal choice: uBlock Origin)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Only with the above 3 steps you’ve achieved:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ISPs cannot see your DNS queries in plain text&lt;&#x2F;li&gt;
&lt;li&gt;Websites cannot serve you random js code in the name of ads&lt;&#x2F;li&gt;
&lt;li&gt;A web browser which is more focussed towards privacy in general&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you’re someone who wants to spend a bit more time (trust me it won’t take even one hour) and a bit of money (one movie ticket a month) you should host your personal VPN. VPNs are awesome because you mitigate a lot of privacy invaders and you are on an anonymous browsing mode &lt;em&gt;generally&lt;&#x2F;em&gt;. Theoretically, we have shifted the trust from the ISP to the cloud provider where VPN is hosted, yes. But as long as you’re not doing anything illegal in the eyes of the state, you should be fine.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Protip&lt;&#x2F;strong&gt;: Don’t use VPN to do something stupid. You are always trackable. The whole exercise is to not allow bad actors to access your personally identifiable information online and have a non-intrusive browsing experience. If you think by using VPNs you can get away with doing something which is illegal by your state then you’re wrong.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tools-i-use&quot;&gt;Tools I use&lt;a class=&quot;zola-anchor&quot; href=&quot;#tools-i-use&quot; aria-label=&quot;Anchor link for: tools-i-use&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;VPN: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wireguard.com&#x2F;&quot;&gt;Wireguard&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Adblocking: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pi-hole.net&#x2F;&quot;&gt;Pi-hole&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;DNS Resolver: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nlnetlabs.nl&#x2F;projects&#x2F;unbound&#x2F;about&#x2F;&quot;&gt;Unbound&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The setup is pretty straightforward. I use Wireguard client on my MBP and an Android device to connect to the Wireguard VPN server hosted on a $5 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;&quot;&gt;DO&lt;&#x2F;a&gt; droplet in Bengaluru, India. For ad-blocking, I use Pi-hole, which does DNS based ad-blocking. And finally to resolve the DNS queries I use vanilla unbound without any forwarders.&lt;&#x2F;p&gt;
&lt;p&gt;Read the following sections to know more on each of the above pieces.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-up-wireguard-vpn&quot;&gt;Setting up wireguard VPN&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-wireguard-vpn&quot; aria-label=&quot;Anchor link for: setting-up-wireguard-vpn&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Wireguard gets all the love from me (thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;iamd3vil&quot;&gt;@sarat&lt;&#x2F;a&gt; for telling me about this). It is probably the best option out there if you’re looking to self-host a VPN. Wireguard gets a lot of things right, first being the ease of setup. Literally takes a few commands and you’re all set. Wireguard is very lightweight and consumes minimal resources. Wireguard has better encryption and is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wireguard.com&#x2F;performance&#x2F;&quot;&gt;lot faster&lt;&#x2F;a&gt; than IPvsec or open VPN. Cloudflare’s new app Warp is also based on Wireguard. Oh, and did I mention that Wireguard seamlessly transitions when you switch networks (which happens all the time when you’re on shitty 4G network&#x2F;public WiFis).&lt;&#x2F;p&gt;
&lt;p&gt;Wireguard basically has 2 parts. One is the server and the other is the client.
Wireguard sits in its own separate network namespace and uses this namespace as an init namespace from where the traffic is received or sent. This namespace is now responsible for flowing your traffic to the other actual interface your network card on the device (which is probably wlan or eth).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;installing-wireguard&quot;&gt;Installing Wireguard&lt;a class=&quot;zola-anchor&quot; href=&quot;#installing-wireguard&quot; aria-label=&quot;Anchor link for: installing-wireguard&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; add-apt-repository&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ppa:wireguard&#x2F;wireguard&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; apt-get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; apt-get&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wireguard-dkms&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wireguard-tools&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; linux-headers-&lt;&#x2F;span&gt;&lt;span&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;uname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;generating-public-private-key-pair&quot;&gt;Generating Public&#x2F;Private key pair&lt;a class=&quot;zola-anchor&quot; href=&quot;#generating-public-private-key-pair&quot; aria-label=&quot;Anchor link for: generating-public-private-key-pair&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; umask&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 077&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; genkey&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; tee&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; server_private_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pubkey&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; server_public_key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;server_private_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  server_public_key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;configuring-wireguard-server&quot;&gt;Configuring Wireguard (server)&lt;a class=&quot;zola-anchor&quot; href=&quot;#configuring-wireguard-server&quot; aria-label=&quot;Anchor link for: configuring-wireguard-server&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; touch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;wireguard&#x2F;wg0.cong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;wireguard&#x2F;wg0.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add the following lines and modify the values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Interface&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Configuration settings for a separate network interface&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.200.200.1&#x2F;24&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; You can choose any private subnet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;SaveConfig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Wireguard can configure additional peers automatically without reloading wireguard, for some reason this didn&amp;#39;t work well for me&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PrivateKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;redacte&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Output of the `server_private_key` generated in the above setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ListenPort&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 51820&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Default port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Add the peers (clients which connect to the wireguard server)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Peer&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; MBP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PublicKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;laptop_public_ke&lt;&#x2F;span&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;AllowedIPs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.200.200.2&#x2F;32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Peer&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Android&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PublicKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;phone_public_ke&lt;&#x2F;span&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;AllowedIPs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 10.200.200.3&#x2F;32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;configuring-wireguard-client&quot;&gt;Configuring Wireguard (client)&lt;a class=&quot;zola-anchor&quot; href=&quot;#configuring-wireguard-client&quot; aria-label=&quot;Anchor link for: configuring-wireguard-client&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Repeat the step of generating a Public&#x2F;Private key pair. You can also take a look at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;subspacecloud&#x2F;subspace&quot;&gt;Subspace&lt;&#x2F;a&gt; which is a nice GUI tool which helps you create additional profiles for your devices where generating key&#x2F;pair is not convenient like mobile phones. I didn’t get the time to set it up personally, so I generated public&#x2F;private keys from my laptop itself and then configured it manually using an Android app &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;MSF-Jarvis&#x2F;viscerion&quot;&gt;Viscerion&lt;&#x2F;a&gt; which is a wireguard client app.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;For the client, your config file should look like:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Interface]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PrivateKey = &amp;lt;client_private_key&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Address = 10.200.200.2&#x2F;32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Peer]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PublicKey = &amp;lt;server_public_key&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AllowedIPs = 0.0.0.0&#x2F;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Endpoint = &amp;lt;public_ip_droplet&amp;gt;:51820&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PersistentKeepalive = 25&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;recap&quot;&gt;Recap&lt;a class=&quot;zola-anchor&quot; href=&quot;#recap&quot; aria-label=&quot;Anchor link for: recap&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you got overwhelmed at this point, let’s recap what just happened.&lt;&#x2F;p&gt;
&lt;p&gt;We have 2 config files, one for the server and one for the client which happens to be my laptop. On each of the devices, generate a public&#x2F;private key pair.&lt;&#x2F;p&gt;
&lt;p&gt;On the server side, while configuring peer, give the public key of the client. On the client side, while configuring peer,give the public key of the server. This is similar to how &lt;code&gt;ssh&lt;&#x2F;code&gt; works. Wireguard uses &lt;code&gt;Curve25519&lt;&#x2F;code&gt; crypto technique to generate a public&#x2F;private key pair, which honestly &lt;em&gt;looks&lt;&#x2F;em&gt; so better than lengthy ECDSA&#x2F;RSA ones :P&lt;&#x2F;p&gt;
&lt;p&gt;Now let us start the wireguard service. wireguard provides a nice wrapper &lt;code&gt;wg-quick&lt;&#x2F;code&gt; which does the following things when you start:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sudo wg-quick up wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[#] ip link add wg0 type wireguard&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[#] wg setconf wg0 &#x2F;dev&#x2F;fd&#x2F;63&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[#] ip -4 address add 10.200.200.1&#x2F;24 dev wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[#] ip link set mtu 1420 up dev wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can verify a new network interface now by:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ ip addr | grep wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5: wg0: &amp;lt;POINTOPOINT,NOARP,UP,LOWER_UP&amp;gt; mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inet 10.200.200.1&#x2F;24 scope global wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also view the wireguard connection status by:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ sudo wg show&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;interface: wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  public key: &amp;lt;REDACTED&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  private key: (hidden)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  listening port: 51820&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;peer: &amp;lt;REDACTED&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  allowed ips: 10.200.200.2&#x2F;32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;almost-there-but-not-quite&quot;&gt;Almost There, But Not Quite&lt;a class=&quot;zola-anchor&quot; href=&quot;#almost-there-but-not-quite&quot; aria-label=&quot;Anchor link for: almost-there-but-not-quite&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Turn on your wireguard client and you will notice a strange thing. At this point, you’re not able to browse the internet but you are able to connect to the wireguard server and even wireguard is acknowledging that (notice the last two lines in the following snippet):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ sudo wg show&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;interface: wg0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  public key: &amp;lt;REDACTED&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  private key: (hidden)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  listening port: 51820&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;peer: &amp;lt;client_public_key&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  endpoint: &amp;lt;client_public_ip&amp;gt;:64882&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  allowed ips: 10.200.200.2&#x2F;32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  *latest handshake: 8 seconds ago*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  *transfer: 754.60 KiB received, 5.59 MiB sent*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wireguard status shows that our client can reach the wireguard server. But still, we’re unable to browse the internet on our client.&lt;&#x2F;p&gt;
&lt;p&gt;To debug this further, let’s use &lt;code&gt;tcpdump&lt;&#x2F;code&gt; and monitor the packets coming in &lt;code&gt;wg0&lt;&#x2F;code&gt; interface. Since tcpdump’s output can be overwhelming and contains a lot of noise, let’s filter to monitor only the ICMP packets. So we’ll be using &lt;code&gt;ping&lt;&#x2F;code&gt; from a client which is the easiest way to send ICMP packets from point A to point B.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; on wireguard client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;➜&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  ~&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ping&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; icanhazip.com&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;  %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Total&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Received&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Xferd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Average&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; Speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;     Time&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Current&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;                                 Dload&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Total&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   Spent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;    Left&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Speed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    14&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    14&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;     16&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;      0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-:--:--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-:--:--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-:--:--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;    16&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_ip_redacte&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&amp;lt;server_ip_redacted&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;): 56 data bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_ip_redacte&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; icmp_seq=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ttl=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; time=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;112.126&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_ip_redacte&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; icmp_seq=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ttl=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; time=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;142.980&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;^C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_ip_redacte&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; statistics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;--&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; packets&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; transmitted,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; packets&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; received,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0.0%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; packet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; loss&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; on wireguard server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tcpdump&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;nni&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; icmp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcpdump:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; verbose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; suppressed,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; use&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;vv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; full&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; protocol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; decode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;listening&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; on&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg0,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; link-type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; RAW&lt;&#x2F;span&gt;&lt;span&gt; (Raw&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span&gt;), capture size 262144 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;14:26:31.991498&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.200.200.2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_ip_redacte&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ICMP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; request,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 52630,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; length&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;14:26:33.027288&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10.200.200.2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;server_ip_redacte&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ICMP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; request,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 52630,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 1,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; length&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Okay, this is getting interesting. wg0 is definitely receiving packets from our client. Arghhh. &lt;em&gt;Now&lt;&#x2F;em&gt; does it strike to you? Our actual network routing is through &lt;code&gt;eth0&lt;&#x2F;code&gt; (on DO usually) and &lt;code&gt;wg0&lt;&#x2F;code&gt; is just some interface created by Wireguard. They have no “connection” (no pun intended) between them. Let us confirm if this actually is the problem by detecting ICMP traffic on this interface(&lt;code&gt;eth0&lt;&#x2F;code&gt;) using the same command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; on wireguard server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tcpdump&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;nni&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; icmp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;tcpdump:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; verbose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; suppressed,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; use&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;vv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; full&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; protocol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; decode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;listening&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; on&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; link-type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; RAW&lt;&#x2F;span&gt;&lt;span&gt; (Raw&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; IP&lt;&#x2F;span&gt;&lt;span&gt;), capture size 262144 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; nothing happens even if we are sending PING from client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wow, see? No ICMP packets received on &lt;code&gt;eth0&lt;&#x2F;code&gt;. So that indeed is the problem and we have zero’ed it down using &lt;code&gt;tcpdump&lt;&#x2F;code&gt;.
(Note to self: Learn more Linux debugging utils, these things are a godsend!)&lt;&#x2F;p&gt;
&lt;p&gt;In order to fix this, we need to do 2 things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;IP Forwarding&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ vim &#x2F;etc&#x2F;sysctl.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# check for this line and replace the value from 0 to 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;net.ipv4.ip_forward = 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ sudo sysctl -p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;IP Tables Rules&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We need to set up NAT between &lt;code&gt;eth0&lt;&#x2F;code&gt;(could be different for you) and &lt;code&gt;wg0&lt;&#x2F;code&gt;. This can be done using &lt;code&gt;iptables&lt;&#x2F;code&gt; and wireguard actually has a nice mechanism to run custom commands using &lt;code&gt;PostUp&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;PostDown&lt;&#x2F;code&gt; signals.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; on wireguard server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;wireguard&#x2F;wg0.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; add these lines in [Interface] section&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PostUp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; FORWARD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; POSTROUTING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MASQUERADE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; ip6tables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; FORWARD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; ip6tables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; POSTROUTING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MASQUERADE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Configure iptables to setup a NAT on eth0 and forward the packets (ipv4 and ipv6) on interface wg0 to eth0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;PostDown&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; FORWARD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; POSTROUTING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MASQUERADE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; ip6tables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; FORWARD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wg0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; ip6tables&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; POSTROUTING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; MASQUERADE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Delete the rule since when wireguard is down, wg0 doesn&amp;#39;t exist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now everything’s set up and we are browsing the internet privately using a VPN. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ipleak.net&#x2F;&quot;&gt;Ensure&lt;&#x2F;a&gt; that your public IP is of the VPN server when you’re browsing and it’s not leaking.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-pi-hole&quot;&gt;Setting up Pi-hole&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-pi-hole&quot; aria-label=&quot;Anchor link for: setting-up-pi-hole&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Installing Pi-hole is as simple as&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;sSL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; https:&#x2F;&#x2F;install.pi-hole.net&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can read more about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.pi-hole.net&#x2F;main&#x2F;basic-install&#x2F;&quot;&gt;installation&lt;&#x2F;a&gt; in the official docs.&lt;&#x2F;p&gt;
&lt;p&gt;A nice GUI is always a plus, so make sure you enable that option while installing Pi-hole.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;pihole-dashboard.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, we need to configure our Wireguard client to use Pi-hole as a nameserver for DNS resolution.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; on the client add the following line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;wireguard&#x2F;wg0.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Interface&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;DNS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;vpn_server_public_i&lt;&#x2F;span&gt;&lt;span&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pi-hole runs on port 53 and accepts DNS queries over UDP. Any query is first checked by Pi-hole in the blacklist. If it’s present in the blacklist, it’s immediately dropped. If not, Pi-hole will forward our DNS query to one of the forwarder configured (1.1.1.1 for eg or our custom server, explained in the next step).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-unbound-dns&quot;&gt;Setting up Unbound DNS&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-unbound-dns&quot; aria-label=&quot;Anchor link for: setting-up-unbound-dns&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I don’t mind trusting Cloudflare. But I simply don’t have to. :) And once you make peace with the fact that you don’t need 3rd party companies controlling your networking stack, you’ll sleep better.&lt;&#x2F;p&gt;
&lt;p&gt;I have setup Unbound without any forwarders. Unbound is a recursive resolver which supports DNSSec and caching mainly. Unbound first checks if the query exists in cache and if it does, it directly returns the “answer”. Otherwise it talks to the root nameserver and then the whole DNS dance happens. Since our DNS query is now split into multiple parts, where each nameserver is only being queried for a part of the FQDN (also known as QNAME minimialistion), it becomes a lot harder for anyone to intercept or reconstruct your DNS queries.&lt;&#x2F;p&gt;
&lt;p&gt;You can install unbound using&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ sudo apt-get install unbound&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To start using Unbound, we need a file &lt;code&gt;root.hints&lt;&#x2F;code&gt; which contains information about root nameservers. You can cron this to fetch a new copy every once in 3-4 months, it hardly changes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; wget&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; root.hints&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; https:&#x2F;&#x2F;www.internic.net&#x2F;domain&#x2F;named.root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; root.hints&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;var&#x2F;lib&#x2F;unbound&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; unbound&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; restart&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can verify if the DNS queries are being resolved by:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; 6363 is where I have configured my Unbound server to listen&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;dig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; mrkaran.dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; @127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 6363&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pi-hole official docs have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.pi-hole.net&#x2F;guides&#x2F;unbound&#x2F;&quot;&gt;great&lt;&#x2F;a&gt; explainer on how to configure Unbound with Pi-hole so I won’t be repeating the steps here again.&lt;&#x2F;p&gt;
&lt;p&gt;You can configure Pi-hole to forward accepted DNS queries from port &lt;code&gt;53&lt;&#x2F;code&gt; (standard) to &lt;code&gt;127.0.0.1#6363&lt;&#x2F;code&gt; (unbound).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;pihole-dns.png&quot; alt=&quot;PiHole DNS&quot; title=&quot;PiHole DNS&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-endgame&quot;&gt;The Endgame&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-endgame&quot; aria-label=&quot;Anchor link for: the-endgame&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I plan to self-host a couple of more things. DNS is something I am really interested in and in future I plan to host my own DNScrypt server &lt;em&gt;soon-ish&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I believe if you &lt;em&gt;own&lt;&#x2F;em&gt; your data you’re in better control of your digital identity. Watching too much of Black Mirror added to the paranoia to an extent, I suppose! I grew up in the late nineties and I’ve seen the internet primarily as a set of the decentralized toolchain. There’s no reason we should let go any of that to the hands of a few corp giants and make it centralized.&lt;&#x2F;p&gt;
&lt;p&gt;Ending this long-ish post by a beautiful quote:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Study after study has shown that human behaviour changes when we know we’re being watched. Under observation, we act less free, which means we effectively &lt;em&gt;are&lt;&#x2F;em&gt; less free.
― Edward Snowden&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Cheers! :)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Common Docker Mistakes - Episode 1</title>
        <published>2019-04-15T10:57:55+05:30</published>
        <updated>2019-04-15T10:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/docker-mistakes-1/"/>
        <id>https://mrkaran.dev/posts/docker-mistakes-1/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/docker-mistakes-1/">&lt;p&gt;So, off late, I’ve been dabbling a lot with Docker to explore the world of containerization (too late to the party, eh?). I plan to write about some common docker gotchas. The plan is to document these learnings so they might help someone getting started with docker and also serve as a reference for myself in the future. Let me be clear, if you read the docs you will find the exact same information and there’s nothing new that I have discovered. It took me some time to get around the following issues and I believe some of you might be struggling with the same. I just feel when you’re starting out with completely new technology, things quickly can become overwhelming and it’s A-OK to feel so. The important part is to not get intimidated by it and focus on learning the basics. Different pieces start coming together and there you have a solved puzzle :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-mysterious-case-of-bind-mounts-and-volumes&quot;&gt;The mysterious case of bind mounts and volumes&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-mysterious-case-of-bind-mounts-and-volumes&quot; aria-label=&quot;Anchor link for: the-mysterious-case-of-bind-mounts-and-volumes&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Ah! Storage. It’s always not a rosy scenario whenever someone mentions storage and containers in the same sentence. Anyway, so I had this requirement where I needed 2 containers to share data. Either of the containers could modify this data, so it made for a strong use case for volumes. But for some strange reason, I decided to use bind mounts. My thought process was that I’ll bind the mount path of the host to container and both of them could share the data.
Now, I know, I know all the docker veterans already facepalming so hard, but in case anyone new to docker is reading it, it works the exact way I described. The host path will be mounted ON the container, so if your host path is empty, so will your container be. It took me quite some time to figure this out because of the side effect of it. I had this line in my docker-compose:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;etc&#x2F;custom&#x2F;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can guess, I am mounting an empty folder &lt;code&gt;etc&#x2F;custom&#x2F;data&lt;&#x2F;code&gt; on the root directory of the container &lt;code&gt;&#x2F;&lt;&#x2F;code&gt;. This was an &lt;code&gt;nginx&lt;&#x2F;code&gt; container and I got the weird error that &lt;code&gt;nginx&lt;&#x2F;code&gt; executable isn’t found. It became clear that I have obviously done something wrong. After reading the documentation, it became clear that I had to use something like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;storage&#x2F;volumes&#x2F;&quot;&gt;Named Volumes&lt;&#x2F;a&gt; and use the same volume label for both the containers. Here’s the correct docker compose example (I have removed the unnecessary fluff and only included the volumes part):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ginx&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olume&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ssets-vol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;usr&#x2F;share&#x2F;nginx&#x2F;frontend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rontend&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olume&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ssets-vol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;arget&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;frontend&#x2F;dist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ssets-vol&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;assets-vol&lt;&#x2F;code&gt; is a named volume and can be managed using docker API.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cmd-vs-run&quot;&gt;CMD vs RUN&lt;a class=&quot;zola-anchor&quot; href=&quot;#cmd-vs-run&quot; aria-label=&quot;Anchor link for: cmd-vs-run&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now, this is particularly interesting. So I have a volume mount as shown in the previous example, and quite naively I am copying some files from container 1 to container 2 at build stage. I get the error that this path doesn’t exist. I am seriously reconsidering my life decisions right now.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;RUN cp &#x2F;frontend&#x2F;dist &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;frontend&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And then it became apparent that the volume is only mounted while the container is running, not when it is building. So I had to use CMD.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;CMD cp &#x2F;frontend&#x2F;dist &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;frontend&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Why &lt;code&gt;RUN&lt;&#x2F;code&gt; doesn’t work and &lt;code&gt;CMD&lt;&#x2F;code&gt; works, you might ask? This is because that’s how docker volumes are in nature. They bypass the unionFS (which is used to build docker images). UnionFS chain together a layer of images and build new images on top. Whenever you run a container from an image, a new layer is created for the container process. If you specify a path as a volume, this path doesn’t get &lt;code&gt;committed&lt;&#x2F;code&gt; to the container data layer and is bypassed. So, TL;DR, volumes are really only accessible when the container is running and you can’t access them while building.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;epilogue&quot;&gt;Epilogue&lt;a class=&quot;zola-anchor&quot; href=&quot;#epilogue&quot; aria-label=&quot;Anchor link for: epilogue&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I plan to share more such silly mistakes of mine while exploring more of Docker (and hopefully running production workloads on it soon!). It really is fun though, believe me :)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Setting up Kong API Gateway - Part 2&#x2F;2</title>
        <published>2019-03-23T11:57:55+05:30</published>
        <updated>2019-03-23T11:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/setting-up-kong-part-2/"/>
        <id>https://mrkaran.dev/posts/setting-up-kong-part-2/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/setting-up-kong-part-2/">&lt;h1 id=&quot;managing-kong-using-ui&quot;&gt;Managing Kong using UI&lt;a class=&quot;zola-anchor&quot; href=&quot;#managing-kong-using-ui&quot; aria-label=&quot;Anchor link for: managing-kong-using-ui&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pantsel&#x2F;konga&quot;&gt;Konga&lt;&#x2F;a&gt; is an &lt;em&gt;unofficial&lt;&#x2F;em&gt; project which is basically an UI for Admin API of Kong. This post is about how to setup Konga and configuring an upstream service. We will also add an authentication layer to our upstream.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;docker-to-the-rescue&quot;&gt;Docker to the rescue&lt;a class=&quot;zola-anchor&quot; href=&quot;#docker-to-the-rescue&quot; aria-label=&quot;Anchor link for: docker-to-the-rescue&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We will use Docker to quickly setup Konga as it a Node.js project and it is a lot of trouble building node projects on server, so let’s just use Docker.&lt;&#x2F;p&gt;
&lt;p&gt;Our &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; for reference:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;3.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ostgres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;estart&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lways&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;432:5432&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;OSTGRES_PASSWORD&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;lt;redacted&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;home&#x2F;ubuntu&#x2F;docker&#x2F;volumes&#x2F;postgresql&#x2F;:&#x2F;var&#x2F;lib&#x2F;postgresql&#x2F;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ockergalaxy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;pp&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;antsel&#x2F;konga:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;estart&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;lways&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;337:1337&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;B_URI&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;postgresql:&#x2F;&#x2F;user_redacted:pass_redacted@db:5432&#x2F;db_redacted&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;      D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;B_ADAPTER&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ockergalaxy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ginx&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ginx:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;orts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;0:80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;43:443&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;home&#x2F;ubuntu&#x2F;docker&#x2F;volumes&#x2F;nginx&#x2F;conf&#x2F;:&#x2F;etc&#x2F;nginx&#x2F;conf.d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;home&#x2F;ubuntu&#x2F;docker&#x2F;volumes&#x2F;nginx&#x2F;ssl&#x2F;:&#x2F;etc&#x2F;ssl&#x2F;certs&#x2F;konga&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ockergalaxy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;etworks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ockergalaxy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker-compose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pull&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;docker-compose&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; up&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Verify, if all 3 containers are up.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ps&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;CONTAINER&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                  COMMAND&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                  CREATED&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;             STATUS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;              PORTS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                                      NAMES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5f20abcd81fc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        nginx:latest&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;           &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;nginx -g &amp;#39;daemon of…&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;   29&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hours&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ago&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        Up&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 28&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hours&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         0.0.0.0:80&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;80&#x2F;tcp,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; 0.0.0.0:443&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;443&#x2F;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   deployment_nginx_1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ff20abcd24a66&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        pantsel&#x2F;konga:latest&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;   &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;app&#x2F;start.sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;          30&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hours&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ago&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        Up&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 29&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hours&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         0.0.0.0:1337&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1337&#x2F;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                     deployment_app_1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;5848abcd27d2a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;               &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;docker-entrypoint.s…&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;   30&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hours&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ago&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        Up&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 29&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; hours&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;         0.0.0.0:5432&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;5432&#x2F;tcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;                     deployment_db_1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Konga is running on port &lt;code&gt;1337&lt;&#x2F;code&gt; and you can verify the same by doing a &lt;code&gt;curl&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http:&#x2F;&#x2F;localhost:1337&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; should return HTTP 200&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;adding-an-upstream-to-kong&quot;&gt;Adding an Upstream to Kong&lt;a class=&quot;zola-anchor&quot; href=&quot;#adding-an-upstream-to-kong&quot; aria-label=&quot;Anchor link for: adding-an-upstream-to-kong&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Visit Konga Admin Dashboard to login. If this is a first time login, you need to activate the connection to Kong’s Admin API by visiting Connections tab. This step needs to be done by each admin user, individually.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-0.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Some common terminology before we begin setting up our APIs: (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.konghq.com&#x2F;1.0.x&#x2F;proxy&#x2F;#terminology&quot;&gt;Source&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Term&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;client&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Refers to the downstream client making requests to Kong’s proxy port.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;upstream service&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Refers to your own API&#x2F;service sitting behind Kong, to which client requests are forwarded.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Service&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Service are abstraction of each of your own upstream services.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Route&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Routes are entrypoints into Kong, and defining rules for a request to be matched, and routed to a given Service.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Plugin&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;This refers to Kong “plugins”, which are pieces of business logic that run in the proxying lifecycle. Plugins can be configured for an individual route, or a service or globally. An example of plugin which we use is &lt;code&gt;Key Auth&lt;&#x2F;code&gt; plugin for authentication.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;adding-new-service&quot;&gt;Adding New Service&lt;a class=&quot;zola-anchor&quot; href=&quot;#adding-new-service&quot; aria-label=&quot;Anchor link for: adding-new-service&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Visit the Services section and click on &lt;strong&gt;Add new Service&lt;&#x2F;strong&gt;. Enter the following details for your upstream service here. You can refer to the below screenshot for reference:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-1.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Name&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Add a unique name for your upstream service.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Description&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Service description.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Tags&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;List of tags to identify a group of services together. Press &lt;strong&gt;ENTER&lt;&#x2F;strong&gt; for any kind of array values in Konga UI.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;URL&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Shorthand for setting &lt;code&gt;Host&lt;&#x2F;code&gt;, &lt;code&gt;Path&lt;&#x2F;code&gt;, &lt;code&gt;Protocol&lt;&#x2F;code&gt; with just one value. Note that this is only a feature in Konga, Kong doesn’t have it, when using it with the Admin API calls directly.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Verify the details once and click on Save. Next, we’ll see how to add routes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;adding-routes-to-services&quot;&gt;Adding Routes to Services&lt;a class=&quot;zola-anchor&quot; href=&quot;#adding-routes-to-services&quot; aria-label=&quot;Anchor link for: adding-routes-to-services&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Visit the Services section and click on the service entity you just created.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-2.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Go to the routes section and add the a new route entry for the service. You can refer to the below screenshot for reference:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-3.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Name&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Add a unique name for your route.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Hosts&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Kong checks for the hostname present in the incoming request’s header. If you specify this value then the Hostname &lt;strong&gt;must&lt;&#x2F;strong&gt; be present for Kong to match the request to this route. This is suitable only if you want to block any request made outside this hostname. You can leave it null if not needed.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Path&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;List of paths present in incoming request. This is required to namespace the upstream endpoints. The client must send this prefix in the request, Kong will try to match any request’s path in this list of paths and based on the settint of &lt;code&gt;strip_path&lt;&#x2F;code&gt; the request will be proxied.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Strip Path&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Boolean value, which configures Kong to strip the matching path from the incoming request to the upstream URL.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;how-routing-actually-works&quot;&gt;How routing actually works&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-routing-actually-works&quot; aria-label=&quot;Anchor link for: how-routing-actually-works&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Kong has the ability to configure really complex routing endpoints based on your usecases. For the simplicity and keeping this guide as generic, the basic (but most common) use case is discussed below by taking an example.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s say your upstream URL(&lt;code&gt;service&lt;&#x2F;code&gt;) is &lt;code&gt;http:&#x2F;&#x2F;jsonplaceholder.typicode.com&#x2F;&lt;&#x2F;code&gt;. To setup Kong for this service, we will simply add a route, with the path as &lt;code&gt;&#x2F;fake&lt;&#x2F;code&gt;. Here the &lt;code&gt;path&lt;&#x2F;code&gt; acts as a namespace, to differentiate between different services. This can be helpful to avoid route collision if there are a lot of upstream services configured.&lt;&#x2F;p&gt;
&lt;p&gt;Consider the upstream API endpoint is &lt;code&gt;https:&#x2F;&#x2F;jsonplaceholder.typicode.com&#x2F;todos&#x2F;&lt;&#x2F;code&gt;.
If we specify Kong to have the &lt;code&gt;path&lt;&#x2F;code&gt; as &lt;code&gt;&#x2F;fake&lt;&#x2F;code&gt; and set the &lt;code&gt;strip_path&lt;&#x2F;code&gt; as &lt;code&gt;True&lt;&#x2F;code&gt; then our incoming request should look like
&lt;code&gt;https:&#x2F;&#x2F;kongapigateway.com&#x2F;fake&#x2F;todos&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Kong will try to match the path &lt;code&gt;&#x2F;fake&lt;&#x2F;code&gt; in this incoming request and look for the routes where the path is &lt;code&gt;&#x2F;fake&lt;&#x2F;code&gt;. Since it found the correct route, and we have set &lt;code&gt;strip_path&lt;&#x2F;code&gt; to &lt;code&gt;True&lt;&#x2F;code&gt;, Kong will just remove this particular &lt;code&gt;path&lt;&#x2F;code&gt; prefix while reverse proxying to the upstream URL. In this way, our upstream doesn’t need to be concerned about the &lt;code&gt;path&lt;&#x2F;code&gt; prefix as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;adding-consumers&quot;&gt;Adding Consumers&lt;a class=&quot;zola-anchor&quot; href=&quot;#adding-consumers&quot; aria-label=&quot;Anchor link for: adding-consumers&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Step 1:
Visit the Consumers section to add consumers for your API. Here the consumers doesn’t really mean 1:1 users, it could be a particular production service wanting to &lt;em&gt;consume&lt;&#x2F;em&gt; another service’s API.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Step 2:
Click on &lt;strong&gt;Add new consumer&lt;&#x2F;strong&gt; and enter the following details:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-4.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Step 3:
Add the remaining details in the groups section. Visit the Credentials sections, click on &lt;code&gt;API Keys&lt;&#x2F;code&gt; (since we are using Key Auth plugin for authentication) and simply click on &lt;strong&gt;Submit&lt;&#x2F;strong&gt; button, since Kong will auto generate the API key for you (which most likely will be more secure than any random key you will enter).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-5.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-6.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Step 4:
Leave the other details as it is. We will add this consumer to our Services page. Visit the services tab, click on the service entity you created and
go to Plugins section. Click on &lt;strong&gt;Add New Plugin&lt;&#x2F;strong&gt; and the select Key Auth from the list.
&lt;img src=&quot;&#x2F;images&#x2F;kong-7.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In the modal that opens up, you need to specify the consumer UUID which was created (or leave it as blank for all consumers to access). More on controlling the access, is present later in the next section.
&lt;img src=&quot;&#x2F;images&#x2F;kong-8.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Step 5:
This feels a bit out of the flow, but after checking out Kong docs, there’s no alternate for this. In the previous step you would have been wondering, what if you need multiple consumers for the service, and want to identify them individually. Since Kong requires you to give either the Consumer UUID or leave it blank so all consumers are tied, the way around this is to use another plugin, called &lt;strong&gt;ACL Plugin&lt;&#x2F;strong&gt;. With this plugin, you can whitelist a group of consumers, so only the whitelisted consumers can access the API even though you specified &lt;em&gt;All Consumers&lt;&#x2F;em&gt; in the Key Auth plugin. &lt;em&gt;ACL Plugin&lt;&#x2F;em&gt; must be used in conjuction with another authentication plugin.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can refer to the below screenshot for reference:
&lt;img src=&quot;&#x2F;images&#x2F;kong-9.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kong-10.png&quot; alt=&quot;image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;NOTE&lt;&#x2F;em&gt;: This is the same group, which you created at the time of Consumer creation. You can group different consumers based on the service they consume, hence the naming convention one &lt;em&gt;can&lt;&#x2F;em&gt; follow is &lt;em&gt;&lt;service-name&gt;-consumers&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can see all the eligible consumers for the service, in &lt;em&gt;Eligible Consumers&lt;&#x2F;em&gt; tab.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-kong-as-an-end-user&quot;&gt;Using Kong as an end user&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-kong-as-an-end-user&quot; aria-label=&quot;Anchor link for: using-kong-as-an-end-user&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You need to replace your upstream API endpoints and all other custom authentication with just the Kong’s URL, the namespace for the service, and add
the authentication keys in header while sending the request.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;p&gt;If your original request is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;X&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; GET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; http:&#x2F;&#x2F;jsonplaceholder.typicode.com&#x2F;todos&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The modified request becomes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;X&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; GET&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; https:&#x2F;&#x2F;kongapigateway.com&#x2F;fake&#x2F;todos&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-header&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;X-ACCESS: ENTER_KEY_HERE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;accessing-user-authentication-details-in-your-api&quot;&gt;Accessing user authentication details in your API&lt;a class=&quot;zola-anchor&quot; href=&quot;#accessing-user-authentication-details-in-your-api&quot; aria-label=&quot;Anchor link for: accessing-user-authentication-details-in-your-api&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can remove all custom authentication method in your API services as Kong forwards the user information in the headers. You can use the following headers while processing the incoming request to identify the users and implement custom business logic:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Header Key&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;X-Consumer-ID&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ID of the Consumer on Kong&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;X-Consumer-Custom-ID&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;custom_id of the Consumer (if set)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;X-Consumer-Username&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;username of the Consumer (if set)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;X-Anonymous-Consumer&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;will be set to true when authentication failed, and the ‘anonymous’ consumer was set instead.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;X-Credential-Username&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;the username of the Credential (only if the consumer is not the ‘anonymous’ consumer)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;the-end&quot;&gt;The End&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-end&quot; aria-label=&quot;Anchor link for: the-end&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Hope you liked the two part series of setting up and managing your Kong cluster. Do reach out to me &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;@mrkaran_&quot;&gt;@mrkaran_&lt;&#x2F;a&gt; in case of any feedback for the post. Thanks!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Setting up Kong API Gateway - Part 1&#x2F;2</title>
        <published>2019-03-23T10:57:55+05:30</published>
        <updated>2019-03-23T10:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/setting-up-kong-part-1/"/>
        <id>https://mrkaran.dev/posts/setting-up-kong-part-1/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/setting-up-kong-part-1/">&lt;h1 id=&quot;kong&quot;&gt;Kong&lt;a class=&quot;zola-anchor&quot; href=&quot;#kong&quot; aria-label=&quot;Anchor link for: kong&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;konghq.com&#x2F;&quot;&gt;Kong&lt;&#x2F;a&gt; is an API Gateway, which basically reverse proxies every incoming request to the upstream URL. It is pretty useful if you have a lot of internal services which need to talk to each other (through HTTP) but you don’t want to keep managing the authentication layer, rate limiting, hosts whitelisting and other such things in every service. Kong acts as a central entrypoint to all other services’ API endpoints and all the common fluff is heavylifted by Kong’s API layer.&lt;&#x2F;p&gt;
&lt;p&gt;Kong follows a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.konghq.com&#x2F;hub&#x2F;&quot;&gt;plugin&lt;&#x2F;a&gt; approach, which makes it extensible and you can even &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.konghq.com&#x2F;gateway&#x2F;latest&#x2F;plugin-development&#x2F;&quot;&gt;make your own plugins&lt;&#x2F;a&gt;. Using plugins, it is possible to modify the request,
add authentication layer at the Kong layer, forward user meta information headers to the upstream.&lt;&#x2F;p&gt;
&lt;p&gt;Amongst other API Gateway solutions, Kong is pretty straightforward to get started with and has a nice community support as well. All of the actions to configure your API endpoints and manage them can be done through a RESTful Admin API.&lt;&#x2F;p&gt;
&lt;p&gt;The following setup guide describes how the infra is setup for &lt;strong&gt;High Availability&lt;&#x2F;strong&gt; of a cluster of Kong nodes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;infra-setup&quot;&gt;Infra Setup&lt;a class=&quot;zola-anchor&quot; href=&quot;#infra-setup&quot; aria-label=&quot;Anchor link for: infra-setup&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Each individual Kong node is stateless, since it is always connected to an external datastore. In this tutorial, we will provision 2 nodes for Kong. The instances are frontended by Amazon’s ELB which routes the traffic internally to either of a Kong node using internal DNS. Kong requires a datastore to fetch the information about upstream APIs, consumers, routing mechanisms, plugins, so each of the Kong node must be in sync with the other Kong node. We will achieve the same by using Cassandra as our database for Kong, which is being run in a clustering mode. Cassandra uses it’s gossip mechanism to ensure the other Cassandra node is upto-date with any new changes to the data.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;scaling-kong&quot;&gt;Scaling Kong&lt;a class=&quot;zola-anchor&quot; href=&quot;#scaling-kong&quot; aria-label=&quot;Anchor link for: scaling-kong&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;To scale Kong in future, we can keep on adding multiple Kong nodes horizontally and attaching them to one of the Cassandra node. This way we can have multiple Kong nodes in one cluster each pointing to one central Cassandra datastore.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-up-the-cluster&quot;&gt;Setting up the cluster&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-the-cluster&quot; aria-label=&quot;Anchor link for: setting-up-the-cluster&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We will use Ansible to automate the task of setting up Kong+Cassandra in each of 2 nodes. You can refer to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;kong-ansible&quot;&gt;playbook&lt;&#x2F;a&gt; which will do the job.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #6CB6FF);&quot;&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; https:&#x2F;&#x2F;github.com&#x2F;mr-karan&#x2F;kong-ansible&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Playbook to install the Cassandra and Kong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;osts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{control_host}}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;emote_user&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{{control_user}}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ecome&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;oles&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ole&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ava&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ole&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;assandra&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ole&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After you run the playbook, there are a couple of important things which needs to be configured in order to have an HA setup. This setup guide
assumes the playbook is run individually on 2 servers: &lt;code&gt;srvr A&lt;&#x2F;code&gt; and &lt;code&gt;srvr B&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;important-directory-paths&quot;&gt;Important Directory Paths&lt;a class=&quot;zola-anchor&quot; href=&quot;#important-directory-paths&quot; aria-label=&quot;Anchor link for: important-directory-paths&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Local location&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;kong&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Kong executable binary&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&#x2F;usr&#x2F;local&#x2F;kong&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;All the settings and logs are available under a namespaced directory, which will be called as &lt;code&gt;PREFIX&lt;&#x2F;code&gt; in further sections.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&#x2F;etc&#x2F;systemd&#x2F;service&#x2F;kong.service&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Managing Kong as systemd service&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&#x2F;etc&#x2F;systemd&#x2F;service&#x2F;cassandra.service&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Managing Cassandra db as systemd service&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&#x2F;etc&#x2F;cassandra&#x2F;cassandra.yaml&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Config for Cassandra&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&#x2F;etc&#x2F;kong&#x2F;kong.conf&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Config for Kong&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;first-steps&quot;&gt;First Steps&lt;a class=&quot;zola-anchor&quot; href=&quot;#first-steps&quot; aria-label=&quot;Anchor link for: first-steps&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;setting-up-cassandra&quot;&gt;Setting up Cassandra&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-cassandra&quot; aria-label=&quot;Anchor link for: setting-up-cassandra&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Let’s setup Cassandra first and run in clustering mode. Do these steps in both of the servers.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Stop any running cassandra node:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cassandra&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Edit the cassandra config file and update the following values:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cluster_name: &amp;#39;KongAPICluster&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;seed_provider:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- class_name: org.apache.cassandra.locator.SimpleSeedProvider&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    parameters:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        - seeds: &amp;quot;&amp;lt;private_ip_srvrA&amp;gt;,&amp;lt;private_ip_srvrB&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;listen_address: &amp;lt;private_ip_srvr&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    start_rpc: true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Start cassandra on both the servers and check the status:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; serice&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cassandra&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Verify Cassandra clustering:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nodetool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Give it a couple of seconds (30-45) for both nodes to warm up and discover each other.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output of above command should look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; nodetool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;Datacenter:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; datacenter1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Status&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;U&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; State=Normal&#x2F;Leaving&#x2F;Joining&#x2F;Moving&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  Address&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;        Load&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       Tokens&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;       Owns&lt;&#x2F;span&gt;&lt;span&gt; (effective&lt;&#x2F;span&gt;&lt;span&gt;)  Host ID   Rack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;UN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;REDACTE&lt;&#x2F;span&gt;&lt;span&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  467.26&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; KiB&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  256&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          100.0%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;REDACTE&lt;&#x2F;span&gt;&lt;span&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  rack1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;UN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;REDACTE&lt;&#x2F;span&gt;&lt;span&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  496.36&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; KiB&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;  256&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;          100.0%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;REDACTE&lt;&#x2F;span&gt;&lt;span&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;  rack1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Troubleshooting Cassandra:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;cqlsh unable to connect to &lt;code&gt;cassandra&lt;&#x2F;code&gt; server:&lt;&#x2F;strong&gt;
&lt;code&gt;cqlsh&lt;&#x2F;code&gt; has a known bug in some versions with Python2.7 where it cannot connect to the cassandra server. Do the following steps to fix:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cassandra-driver&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span&gt; CQLSH_NO_BUNDLED&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;TRUE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Unable to discover the other cassandra cluster:&lt;&#x2F;strong&gt;
This usally happens because of network connectivity issues. Verify both nodes are able to talk to each other by running Cassandra in single cluster mode and then issue the following commands:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; in srvrA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;netstat&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;lntvp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cassandra&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; should be present (port 9042 usually)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; in srvrB, check similarly...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; in srvrA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;telnet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; private_ip_srvrB&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 9042&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; should connect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; in srvrB, check similarly...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;setting-up-kong&quot;&gt;Setting up Kong&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-kong&quot; aria-label=&quot;Anchor link for: setting-up-kong&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Let’s setup each Kong node in the cluster as following.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Stop any running kong instance:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kong&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; stop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Edit the kong config file and update the following values:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;admin_listen&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;private_ip_srvr&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:8001,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;private_ip_srvr&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:8444&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; ssl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;database&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; cassandra&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;db_update_propagation&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;seconds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Start kong on both the servers and check the status:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; serice&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kong&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Verify if Kong is running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; kong&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Run Kong Migrations:&lt;&#x2F;p&gt;
&lt;p&gt;Run the migrations on &lt;em&gt;only&lt;&#x2F;em&gt; one cluster. Since the datastores will be in sync(&lt;em&gt;eventual consistency&lt;&#x2F;em&gt; thanks to Cassandra), we don’t have to run migrations on the second cluster.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;kong&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; migrations&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;path&#x2F;to&#x2F;config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Troubleshooting Kong:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Check if Kong is actually running by &lt;code&gt;sudo service kong status&lt;&#x2F;code&gt;. You can check for logs in &lt;code&gt;$PREFIX&#x2F;logs&#x2F;error.log&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;If Kong is not running, you can try running &lt;code&gt;kong check&lt;&#x2F;code&gt; for checking if the config file is correct. Kong additionally provides a health check command, which can be executed using &lt;code&gt;kong health&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;managing-kong&quot;&gt;Managing Kong&lt;a class=&quot;zola-anchor&quot; href=&quot;#managing-kong&quot; aria-label=&quot;Anchor link for: managing-kong&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Kong comes with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.konghq.com&#x2F;1.0.x&#x2F;admin-api&#x2F;&quot;&gt;Admin API&lt;&#x2F;a&gt; to manage all aspects of Kong. There is also an unofficial project which is aN UI on top of Kong’s API and it comes pretty handy to configure upstream endpoints, adding plugins etc.&lt;&#x2F;p&gt;
&lt;p&gt;To read more about it, you can continue reading the second part of the series &lt;a href=&quot;&#x2F;posts&#x2F;setting-up-kong-part-2&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Adding Prometheus configuration to your CI&#x2F;CD workflow</title>
        <published>2019-03-17T10:57:55+05:30</published>
        <updated>2019-03-17T10:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/prometheus-ci/"/>
        <id>https://mrkaran.dev/posts/prometheus-ci/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/prometheus-ci/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;&quot;&gt;Prometheus&lt;&#x2F;a&gt; configurations can turn into a mess in no time if you have a lot of different jobs scraping different targets. Certainly you can use tools like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jsonnet.org&#x2F;&quot;&gt;jsonnet&lt;&#x2F;a&gt; to keep your &lt;code&gt;YAML&lt;&#x2F;code&gt; files DRY but this post is not about that. I initially started off by writing one job to scrape a set of EC2 instances in a particular AWS VPC. Over the time, I had a requirement to do it over 3-4 different targets, each of them had their own rules and different type of exporters as well. The whole practice of &lt;code&gt;SSH&lt;&#x2F;code&gt;ing into the server, opening the config file in &lt;code&gt;vim&lt;&#x2F;code&gt; and editing in the server didn’t just feel &lt;em&gt;right&lt;&#x2F;em&gt;. No surpises for guessing that I f*cked up a few times with config errors (YAML &lt;em&gt;sigh&lt;&#x2F;em&gt;) and finally decided that I need a better solution for this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ci-cd-for-config-files&quot;&gt;CI&#x2F;CD for config files&lt;a class=&quot;zola-anchor&quot; href=&quot;#ci-cd-for-config-files&quot; aria-label=&quot;Anchor link for: ci-cd-for-config-files&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;“Wait, so now you’re telling me that I need to setup a full fledged pipeline just for a few config files?”, must have been the thought that echo’ed in your head. Before you jump to the conclusion that it’s overdoing things, IMHO it’s not. And it’s not that difficult either to set it up, so why not? After integrating CI in your workflow, you can be confident that no bad syntax in your PromQL queries or in general the &lt;code&gt;YAML&lt;&#x2F;code&gt; syntax would break your monitoring system.&lt;&#x2F;p&gt;
&lt;p&gt;“That sounds amazing, show me teh code already”. Our Pipeline is fairly fairly simple:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Lint the code using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;prometheus&#x2F;prometheus&#x2F;tree&#x2F;master&#x2F;cmd&#x2F;promtool&quot;&gt;promtool&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Push to S3&lt;&#x2F;li&gt;
&lt;li&gt;Write a shell script to pull from S3, put the config in right places and restarts Prometheus systemd service&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;gitlab-pipeline.png&quot; alt=&quot;Gitlab Pipeline&quot; title=&quot;Gitlab Pipeline&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can automate the last step too, but I just wanted to keep atleast one manual check in this system so I decided against it. And since I don’t have a distributed Prometheus setup yet, it’s simple to keep things the old school way here &lt;i class=&quot;em em-smile&quot;&gt;&lt;&#x2F;i&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can do pretty much all of the steps in the above pipeline of any CI of your choice, but I am using &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;gitlab.com&#x2F;&quot;&gt;Gitlab&lt;&#x2F;a&gt;, so here’s a sample &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tages&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;rometheus-lint&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; run this job on stage lint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;olang:1.11-alpine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; pull go1.11 image from official docker repo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;efore_script&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;pk update &amp;amp;&amp;amp; apk add git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; install git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;cript&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;OOS=linux GOARCH=amd64 CGO_ENABLED=0 go get -u github.com&#x2F;prometheus&#x2F;prometheus&#x2F;cmd&#x2F;promtool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; fetches promtool package&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;GOPATH&#x2F;bin&#x2F;promtool check rules rules&#x2F;alerts&#x2F;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; run the `check rules` command for my prometheus rule files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ush-to-s3&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;tage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;eploy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; run this job on stage deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;roduction&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; tag the job metadata in this environment. useful to quickly revert deploys when shit hits the fan&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ython:3.7-alpine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;cript&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ip install awscli&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; adds aws cli tools&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;ws s3 sync prometheus&#x2F;rules s3:&#x2F;&#x2F;mybucket&#x2F;rules&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; pushes our rule config files to s3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;nly&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;efs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; only allow deploy if branch is master.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;aster&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#22863A, #8DDB8C);&quot;&gt;hen&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;anual&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; trigger this job manually&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A brief explanation for the above file:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;stages: Used to define multiple stages in our pipeline and they are executed &lt;strong&gt;in order&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;jobs: &lt;code&gt;prometheus-lint&lt;&#x2F;code&gt; is one job which will be run in the stage &lt;code&gt;lint&lt;&#x2F;code&gt;. I am using Docker executor with Gitlab runner, so the runner agent talks to the docker executor. Gitlab-CI file is basically an API abstracted to hide away these details from the end user so all the CI&#x2F;CD files look pretty much the same but behind the scenes the way they are executed totally depends on the executor you choose. Since we are using Docker executor, the &lt;code&gt;image&lt;&#x2F;code&gt; tag is picked up and the same docker image is pulled from a public docker repo for this job.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;before_script&lt;&#x2F;code&gt; is basically an event which is called before we begin running our actual CI stuff. You can add your project dependencies here.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;script&lt;&#x2F;code&gt; is a list of commands to be executed inside your environment (container for us).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now that we have our basics about the CI&#x2F;CD pipeline in place, let us see what each of the jobs is actually doing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;prometheus-lint&lt;&#x2F;code&gt;: Installs &lt;code&gt;promtool&lt;&#x2F;code&gt; binary and runs it against our &lt;code&gt;rules&#x2F;&lt;&#x2F;code&gt; folder. The default working directory is our repository itself, so we didn’t have to give the absolute path.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;push-to-s3&lt;&#x2F;code&gt;: Installs &lt;code&gt;aws&lt;&#x2F;code&gt; cli tools, so we can push the files to s3. In case you are wondering where are the access key and secret key present, I have added them as protected variables in my project settings, so only the protected branches (eg &lt;code&gt;master&lt;&#x2F;code&gt;) can access them.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;gitlab-env.png&quot; alt=&quot;Gitlab Environment Variables&quot; title=&quot;Gitlab Environment Variables&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;automate-everything-nah-mate&quot;&gt;Automate everything? Nah mate&lt;a class=&quot;zola-anchor&quot; href=&quot;#automate-everything-nah-mate&quot; aria-label=&quot;Anchor link for: automate-everything-nah-mate&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is how the &lt;code&gt;deploy.sh&lt;&#x2F;code&gt; script looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; s3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sync&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; s3:&#x2F;&#x2F;mybucket&#x2F;rules&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;prometheus&#x2F;config&#x2F;rules&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;promtool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; check&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; config&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &#x2F;etc&#x2F;prometheus&#x2F;prometheus.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; service&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; prometheus&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; restart&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As much as I’d like to be a cool hipster and run &lt;code&gt;&#x2F;deploy&lt;&#x2F;code&gt; from my slack bot (last I checked, there’s a legit term for this: &lt;em&gt;ChatOps&lt;&#x2F;em&gt;), I simply don’t prefer that. Having a human intervention before doing critical deployments like this is OK, IMHO. I don’t update the Prometheus config often, so I don’t mind actually SSH-ing into the single instance and triggering a shell script which does the job for me. I also don’t have a distributed Prometheus setup as of yet. Things will definitely change based on your requirements and there’s no one size that fits all.&lt;&#x2F;p&gt;
&lt;p&gt;I’m much more confident now with my config changes and don’t have to pray to the server overlords everytime I restart Prometheus.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;It just works&lt;&#x2F;em&gt; &lt;i class=&quot;em em-stuck_out_tongue_closed_eyes&quot;&gt;&lt;&#x2F;i&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Makefile for Golang projects</title>
        <published>2018-10-11T18:10:55+05:30</published>
        <updated>2018-10-11T18:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/makefiles-intro/"/>
        <id>https://mrkaran.dev/posts/makefiles-intro/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/makefiles-intro/">&lt;p&gt;Makefile is an awesome tool to group together a bunch of different rules and automate your build process. Makefile is used by &lt;code&gt;make&lt;&#x2F;code&gt; which is essentially a file generator tool. It is generally used to compile and build programs from source by following &lt;code&gt;rules&lt;&#x2F;code&gt; listed in the Makefile. People use Makefile for a lot of different purposes as well, for example converting &lt;code&gt;md&lt;&#x2F;code&gt; to &lt;code&gt;html&lt;&#x2F;code&gt; and publish these files to the web server.&lt;&#x2F;p&gt;
&lt;p&gt;Every makefile you see, is composed of rules. A &lt;code&gt;rule&lt;&#x2F;code&gt; is declaration of a &lt;code&gt;target&lt;&#x2F;code&gt; and the commands to be executed to generate the target. A target can be a file or an action to be performed (more on that later).&lt;&#x2F;p&gt;
&lt;p&gt;This is how a rule looks like in a Makefile&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;target:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dependencies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;    recipe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When you run &lt;code&gt;make target&lt;&#x2F;code&gt;, &lt;code&gt;make&lt;&#x2F;code&gt; searches for the rule which begins with this &lt;code&gt;target&lt;&#x2F;code&gt; and executes the dependecies (if required). It then runs a bunch of commands which are listed in the recipe. An important thing to understand here is that &lt;code&gt;make&lt;&#x2F;code&gt; tracks the dependencies by their last modified time. So if the dependencies haven’t changed, then make will complain with &lt;code&gt;make: &#x27;target&#x27; is up to date.&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Enough of theory, let’s get our feet wet by writing our first Makefile. One important thing about &lt;code&gt;Makefile&lt;&#x2F;code&gt; is that you need to use &lt;code&gt;tabs&lt;&#x2F;code&gt; and not &lt;code&gt;spaces&lt;&#x2F;code&gt;. It is one of the rare &lt;code&gt;*nix&lt;&#x2F;code&gt; programs which is whitespace aware and this has been mentioned in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;The_Unix-Haters_Handbook&quot;&gt;The Unix-Haters Handbook&lt;&#x2F;a&gt; as well.&lt;&#x2F;p&gt;
&lt;p&gt;To begin with, let’s write a simple rule which removes any tempory object files using &lt;code&gt;go clean&lt;&#x2F;code&gt; and previous binary file using good ol &lt;code&gt;rm&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;clean:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sample.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;target&lt;&#x2F;code&gt; here is &lt;code&gt;clean&lt;&#x2F;code&gt;. There is something special going on here though. Imagine we have a file called &lt;code&gt;clean&lt;&#x2F;code&gt; in our source directory? Let us try to run &lt;code&gt;make clean&lt;&#x2F;code&gt; now
Our directory structure:.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── Makefile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└── sample.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On running &lt;code&gt;make clean&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;make: `clean&amp;#39; is up to date.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Every target in Makefile by default is a &lt;code&gt;file target&lt;&#x2F;code&gt;. In our case &lt;code&gt;clean&lt;&#x2F;code&gt; is a file target and &lt;code&gt;make&lt;&#x2F;code&gt; tries to build this file &lt;code&gt;clean&lt;&#x2F;code&gt; but since we already have a file with the same name &lt;code&gt;clean&lt;&#x2F;code&gt; in our directory, &lt;code&gt;make&lt;&#x2F;code&gt; is complaining there’s nothing to do.&lt;&#x2F;p&gt;
&lt;p&gt;Moreover, in this case our rule is more of an &lt;code&gt;action&lt;&#x2F;code&gt; rather than building files. So for all such scenarios, &lt;code&gt;make&lt;&#x2F;code&gt; provides an easy way where we can instruct it to just run the rule and ignore any filename in our directory. This is called a &lt;code&gt;PHONY&lt;&#x2F;code&gt; target which is a special kind of target. &lt;code&gt;PHONY&lt;&#x2F;code&gt; is just a way in &lt;code&gt;make&lt;&#x2F;code&gt; to forcefully run a target and not care about generating files. Our aim with this rule is to run 2 commands and that’s about it. So this is the perfect example for using &lt;code&gt;PHONY&lt;&#x2F;code&gt;.
We can add &lt;code&gt;.PHONY&lt;&#x2F;code&gt; target to our Makefile simply by this line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;.PHONY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;clean:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sample.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now when we run &lt;code&gt;make clean&lt;&#x2F;code&gt; we get our expected output&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rm -f sample.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let us extend our Makefile to do some common tasks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;.PHONY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; fresh&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;test&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;build:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;run:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	.&#x2F;sample.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;clean:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sample.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you have worked on any Golang project, these are very trivial actions on any Golang project. You will soon realise the power of Makefile when you have to do these steps repeatedly. Some people might argue then you can use aliases or simple shell scripts for the same. I vehemently disagree with that. Reason being, &lt;code&gt;make&lt;&#x2F;code&gt; is a much more powerful tool than just running commands. &lt;code&gt;make&lt;&#x2F;code&gt; has support for dependency tracking and it will only rebuild whatever is required. If you are working on a huge project where the build times are to the tune of hours, you will soon realise why shell scripts are inferior. Ofcourse, someone can point that they can write a shell script to do even that, by fetching the last modified time but why do the extra work when there’s an already existing tried and tested tool? &lt;code&gt;make&lt;&#x2F;code&gt; also has support for parallel task execution, so you can just pass the flag &lt;code&gt;-j {num}&lt;&#x2F;code&gt; to &lt;code&gt;make&lt;&#x2F;code&gt; and it will run these {num} jobs parallely. All these benefits will be apparent for larger projects, but it is a good habit to write Makefile even for smaller projects.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;imgs.xkcd.com&#x2F;comics&#x2F;compiling.png&quot; alt=&quot;#1 Excuse&quot; title=&quot;Look Ma! Code is compiling&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We will now make our Makefile a bit more sophisticated and introduce variables. If you want to custom name your binary, or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.cloudflare.com&#x2F;setting-go-variables-at-compile-time&#x2F;&quot;&gt;inject variables at compile time&lt;&#x2F;a&gt;, you can declare these variables, for example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;BIN&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; my-awesome-pro.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;HASH&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; rev-parse&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-short&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; HEAD&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;COMMIT_DATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; show&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-format=%ci&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;HASH&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;BUILD_DATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; $(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;shell&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;+%Y-%m-%d %H:%M:%S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;VERSION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;HASH&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt; ($&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;COMMIT_DATE}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can modify our Makefile to use these variables:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;build:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;BIN&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;ldflags=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-X &amp;#39;main.buildVersion=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;VERSION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39; -X &amp;#39;main.buildDate=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;BUILD_DATE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;run:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	.&#x2F;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;test&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;clean:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;BIN&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can auto version our builds and pass variables during the build time with go linker tool, on passing the &lt;code&gt;-X&lt;&#x2F;code&gt; flag. That’s really neat, now whenever we do a &lt;code&gt;make build&lt;&#x2F;code&gt; we get new version of the build automagically.&lt;&#x2F;p&gt;
&lt;p&gt;So now we have a working Makefile which helps us with trivial things, but everytime if we need to change something in our program and check, we still need to do these steps manually: &lt;code&gt;make clean&lt;&#x2F;code&gt;, &lt;code&gt;make build&lt;&#x2F;code&gt; and &lt;code&gt;make run&lt;&#x2F;code&gt;. Won’t it be awesome if we could tell Makefile to do all this with just one command? Programmers are lazy creatures after all &lt;i class=&quot;em em-smiley&quot;&gt;&lt;&#x2F;i&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In the beginning we saw a target is composed of recipe and dependencies. So we can just create a new &lt;code&gt;PHONY&lt;&#x2F;code&gt; target with all these dependencies and any recipe if we want optionally.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;fresh:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; clean&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We created a new &lt;code&gt;target&lt;&#x2F;code&gt; which depends on &lt;code&gt;clean&lt;&#x2F;code&gt; to run first, then &lt;code&gt;build&lt;&#x2F;code&gt; and finally &lt;code&gt;run&lt;&#x2F;code&gt;. So everytime if we make some change in our Go program, all we need to run is &lt;code&gt;make fresh&lt;&#x2F;code&gt;. Awesome, isn’t it?&lt;&#x2F;p&gt;
&lt;p&gt;We will finally add our last target which is a highly opinionated way of generating binaries for different OS and architectures.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;prod:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	goreleaser&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-rm-dist&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;-snapshot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dist&#x2F;linux_amd64&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;BIN&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;-linux.bin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;	rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;rf&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; dist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This target runs &lt;code&gt;goreleaser&lt;&#x2F;code&gt; which is a build automation tool. It then copies the required linux binary to the source directory and removes all the other junk.&lt;&#x2F;p&gt;
&lt;p&gt;You can even extend your Makefile to commit files to a repo, and rsync these binaries to the production server or initiate your CI&#x2F;CD build process. The reason I like Makefile is because it serves as a living documentation for your project on how to build&#x2F;deploy the project making it easier for new contributors to get started.&lt;&#x2F;p&gt;
&lt;h5 id=&quot;some-additional-information&quot;&gt;Some additional information&lt;a class=&quot;zola-anchor&quot; href=&quot;#some-additional-information&quot; aria-label=&quot;Anchor link for: some-additional-information&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you run &lt;code&gt;make&lt;&#x2F;code&gt; without passing any target name, &lt;code&gt;make&lt;&#x2F;code&gt; will run the first target present in the Makefile. To override this, you should set &lt;code&gt;.DEFAULT_GOAL&lt;&#x2F;code&gt; setting and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;html_node&#x2F;Special-Variables.html#Special-Variables&quot;&gt;override the target&lt;&#x2F;a&gt; which you want to make as default.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.PHONY&lt;&#x2F;code&gt; is just one way to tell &lt;code&gt;make&lt;&#x2F;code&gt; that it is a special kind of target, you can also do the same by creating a target without any recipe. Read &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;html_node&#x2F;Force-Targets.html#Force-Targets&quot;&gt;this&lt;&#x2F;a&gt; to know more.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To know more about &lt;code&gt;Makefile&lt;&#x2F;code&gt;, you can read the manual &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;make.html&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I hope you now appreciate &lt;code&gt;Makefile&lt;&#x2F;code&gt; and try it out in your next project. I’d love feedback on this blog post, do reach me out at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&quot;&gt;twitter&lt;&#x2F;a&gt; or &lt;a href=&quot;mailto:karansharma1295@gmail.com&quot;&gt;email&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bi-Weekly Music Post Part 4</title>
        <published>2018-07-28T21:10:55+05:30</published>
        <updated>2018-07-28T21:10:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/biweekly-music-part-4/"/>
        <id>https://mrkaran.dev/posts/biweekly-music-part-4/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/biweekly-music-part-4/">&lt;p&gt;I am writing this post exactly after 30 days of the last one, caught up with some work and I couldn’t write a new post, apologies! To make up for the delay, I have some absolutely gold reccos this time which I believe you will like it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;isaac-gracie-reverie&quot;&gt;Isaac Gracie - reverie&lt;a class=&quot;zola-anchor&quot; href=&quot;#isaac-gracie-reverie&quot; aria-label=&quot;Anchor link for: isaac-gracie-reverie&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=08takkHGMSE&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;08takkHGMSE&#x2F;0.jpg&quot; alt=&quot;Isaac Gracie - reverie&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tash-sultana-jungle&quot;&gt;Tash Sultana - Jungle&lt;a class=&quot;zola-anchor&quot; href=&quot;#tash-sultana-jungle&quot; aria-label=&quot;Anchor link for: tash-sultana-jungle&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=CZvP7PwUAwM&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;CZvP7PwUAwM&#x2F;0.jpg&quot; alt=&quot;Tash Sultana - Jungle&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;18th-dec-tienas&quot;&gt;18th Dec - Tienas&lt;a class=&quot;zola-anchor&quot; href=&quot;#18th-dec-tienas&quot; aria-label=&quot;Anchor link for: 18th-dec-tienas&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=sFZxvUTBJ14&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;sFZxvUTBJ14&#x2F;0.jpg&quot; alt=&quot;18th Dec - Tienas&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pareek-ariana-and-amrina-coke-studio-explorer-2018&quot;&gt;Pareek - Ariana and Amrina, Coke Studio Explorer 2018&lt;a class=&quot;zola-anchor&quot; href=&quot;#pareek-ariana-and-amrina-coke-studio-explorer-2018&quot; aria-label=&quot;Anchor link for: pareek-ariana-and-amrina-coke-studio-explorer-2018&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8Pvs8X8wvIU&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;8Pvs8X8wvIU&#x2F;0.jpg&quot; alt=&quot;Pareek&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;when-the-curtain-falls-greta-van-fleet&quot;&gt;When The Curtain Falls - Greta Van Fleet&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-the-curtain-falls-greta-van-fleet&quot; aria-label=&quot;Anchor link for: when-the-curtain-falls-greta-van-fleet&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=hurQgJXtpKI&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;hurQgJXtpKI&#x2F;0.jpg&quot; alt=&quot;When The Curtain Falls&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;poppy-ackroyd-paper&quot;&gt;Poppy Ackroyd - Paper&lt;a class=&quot;zola-anchor&quot; href=&quot;#poppy-ackroyd-paper&quot; aria-label=&quot;Anchor link for: poppy-ackroyd-paper&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=3LR1xpUu9eM&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;3LR1xpUu9eM&#x2F;0.jpg&quot; alt=&quot;Poppy Ackroyd&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nothing-personal-night-riots&quot;&gt;Nothing Personal - Night Riots&lt;a class=&quot;zola-anchor&quot; href=&quot;#nothing-personal-night-riots&quot; aria-label=&quot;Anchor link for: nothing-personal-night-riots&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=BS74kXPRyoc&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;BS74kXPRyoc&#x2F;0.jpg&quot; alt=&quot;Nothing Personal&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Do reach out to me &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&quot;&gt;@mrkaran_&lt;&#x2F;a&gt; with your dose of music reccos.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bi-Weekly Music Post Part 3</title>
        <published>2018-06-28T21:30:55+05:30</published>
        <updated>2018-06-28T21:30:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/biweekly-music-part-3/"/>
        <id>https://mrkaran.dev/posts/biweekly-music-part-3/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/biweekly-music-part-3/">&lt;p&gt;Since the past one week, I’m having troubles in connecting to Spotify from India and my #1 source for discovering music is gone.&lt;i class=&quot;em em-disappointed&quot;&gt;&lt;&#x2F;i&gt;
I’ve started using &lt;code&gt;Saavn&lt;&#x2F;code&gt; but it has crappy recommendations and too much of “Bollywoody”&#x2F;crap shit thrown all over. Also, it requires location access to suggest new
music. LOL is this a joke or what? Like seriously, can’t think of a single reason why a ML algo would require my location to suggest me music.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, this week’s recommendation might be a bit more “Desi” as I’ve discovered some real good bands from our country and our beloved neighbours(ofcourse!)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mist-of-capricorn-agam&quot;&gt;Mist of Capricorn - Agam&lt;a class=&quot;zola-anchor&quot; href=&quot;#mist-of-capricorn-agam&quot; aria-label=&quot;Anchor link for: mist-of-capricorn-agam&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=zkvNnRjIhPE&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;zkvNnRjIhPE&#x2F;0.jpg&quot; alt=&quot;Mist of Capricorn&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rangapura-vihaara-agam&quot;&gt;Rangapura Vihaara - Agam&lt;a class=&quot;zola-anchor&quot; href=&quot;#rangapura-vihaara-agam&quot; aria-label=&quot;Anchor link for: rangapura-vihaara-agam&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=oESni03J8h8&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;oESni03J8h8&#x2F;0.jpg&quot; alt=&quot;Rangapura Vihaara&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;toh-phir-aao-levi-s-live-session-7-by-mustafa-zahid-roxen&quot;&gt;Toh Phir Aao - Levi’s Live Session 7 by Mustafa Zahid &amp;amp; ROXEN&lt;a class=&quot;zola-anchor&quot; href=&quot;#toh-phir-aao-levi-s-live-session-7-by-mustafa-zahid-roxen&quot; aria-label=&quot;Anchor link for: toh-phir-aao-levi-s-live-session-7-by-mustafa-zahid-roxen&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=xbqyLExOeyk&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;xbqyLExOeyk&#x2F;0.jpg&quot; alt=&quot;Toh Phir Aao&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;aankhon-kay-sagar-shafqat-amanat-ali-coke-studio-pakistan-season-2&quot;&gt;Aankhon Kay Sagar - Shafqat Amanat Ali, Coke Studio Pakistan, Season 2&lt;a class=&quot;zola-anchor&quot; href=&quot;#aankhon-kay-sagar-shafqat-amanat-ali-coke-studio-pakistan-season-2&quot; aria-label=&quot;Anchor link for: aankhon-kay-sagar-shafqat-amanat-ali-coke-studio-pakistan-season-2&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=I7xqX51zqoM&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;I7xqX51zqoM&#x2F;0.jpg&quot; alt=&quot;Aankhon Kay Sagar&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hit-me-up-the-prophec&quot;&gt;Hit Me Up - The PropheC&lt;a class=&quot;zola-anchor&quot; href=&quot;#hit-me-up-the-prophec&quot; aria-label=&quot;Anchor link for: hit-me-up-the-prophec&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=3B14osWIJRM&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;3B14osWIJRM&#x2F;0.jpg&quot; alt=&quot;Hit Me Up&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tareefan-reprise-lisa-mishra&quot;&gt;Tareefan Reprise - Lisa Mishra&lt;a class=&quot;zola-anchor&quot; href=&quot;#tareefan-reprise-lisa-mishra&quot; aria-label=&quot;Anchor link for: tareefan-reprise-lisa-mishra&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=_Uksazt6G2M&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;_Uksazt6G2M&#x2F;0.jpg&quot; alt=&quot;Tareefan&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;message-in-a-bottle-the-police&quot;&gt;Message In A Bottle - The Police&lt;a class=&quot;zola-anchor&quot; href=&quot;#message-in-a-bottle-the-police&quot; aria-label=&quot;Anchor link for: message-in-a-bottle-the-police&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MbXWrmQW-OE&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;MbXWrmQW-OE&#x2F;0.jpg&quot; alt=&quot;Message In A Bottle&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;agnes-glass-animals&quot;&gt;Agnes - Glass Animals&lt;a class=&quot;zola-anchor&quot; href=&quot;#agnes-glass-animals&quot; aria-label=&quot;Anchor link for: agnes-glass-animals&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=PhdtdUljThU&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;PhdtdUljThU&#x2F;0.jpg&quot; alt=&quot;Agnes&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;psycho-killer-talking-heads&quot;&gt;Psycho Killer - Talking Heads&lt;a class=&quot;zola-anchor&quot; href=&quot;#psycho-killer-talking-heads&quot; aria-label=&quot;Anchor link for: psycho-killer-talking-heads&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=2fioGtDPNEk&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;2fioGtDPNEk&#x2F;0.jpg&quot; alt=&quot;Psycho Killer&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Do reach out to me &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&quot;&gt;@mrkaran_&lt;&#x2F;a&gt; with your dose of music reccos.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bi-Weekly Music Post Part 2</title>
        <published>2018-06-14T12:30:55+05:30</published>
        <updated>2018-06-14T12:30:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/biweekly-music-part-2/"/>
        <id>https://mrkaran.dev/posts/biweekly-music-part-2/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/biweekly-music-part-2/">&lt;p&gt;Ive looped through Nescafe Basement like 100 times the past two weeks and still cant get enough of it. This is the kind of music I like, the kind that just grows on you until you loop endlessly and then hate it &lt;i class=&quot;em em-stuck_out_tongue_closed_eyes&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, the following is a list of songs that I have discovered and liked the most in the past two weeks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tattva-aswekeepsearching&quot;&gt;Tattva - aswekeepsearching&lt;a class=&quot;zola-anchor&quot; href=&quot;#tattva-aswekeepsearching&quot; aria-label=&quot;Anchor link for: tattva-aswekeepsearching&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=kjxhKCGwiCQ&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;kjxhKCGwiCQ&#x2F;0.jpg&quot; alt=&quot;Tattva&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;koothu-over-coffee-agam&quot;&gt;Koothu Over Coffee - Agam&lt;a class=&quot;zola-anchor&quot; href=&quot;#koothu-over-coffee-agam&quot; aria-label=&quot;Anchor link for: koothu-over-coffee-agam&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=BMC5MU6exiw&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;BMC5MU6exiw&#x2F;0.jpg&quot; alt=&quot;Tattva&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tere-ishq-mein-jo-bhi-nescafe-basement&quot;&gt;Tere Ishq Mein Jo Bhi - Nescafe Basement&lt;a class=&quot;zola-anchor&quot; href=&quot;#tere-ishq-mein-jo-bhi-nescafe-basement&quot; aria-label=&quot;Anchor link for: tere-ishq-mein-jo-bhi-nescafe-basement&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Y9Mzc_DlaWY&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;Y9Mzc_DlaWY&#x2F;0.jpg&quot; alt=&quot;Tere Ishq Mein Jo Bhi&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;houndmouth-sedona&quot;&gt;Houndmouth - Sedona&lt;a class=&quot;zola-anchor&quot; href=&quot;#houndmouth-sedona&quot; aria-label=&quot;Anchor link for: houndmouth-sedona&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Y8wifV5RYr8&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;Y8wifV5RYr8&#x2F;0.jpg&quot; alt=&quot;Houndmouth&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;heavy-collective-soul&quot;&gt;Heavy - Collective Soul&lt;a class=&quot;zola-anchor&quot; href=&quot;#heavy-collective-soul&quot; aria-label=&quot;Anchor link for: heavy-collective-soul&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=46g8zDcziL0&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;46g8zDcziL0&#x2F;0.jpg&quot; alt=&quot;Heavy&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-youth-george-taylor&quot;&gt;The Youth - George Taylor&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-youth-george-taylor&quot; aria-label=&quot;Anchor link for: the-youth-george-taylor&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=nQ9kaCre3qM&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;nQ9kaCre3qM&#x2F;0.jpg&quot; alt=&quot;The Youth&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;porcupine-pigeons-playing-ping-pong&quot;&gt;Porcupine - Pigeons Playing Ping Pong&lt;a class=&quot;zola-anchor&quot; href=&quot;#porcupine-pigeons-playing-ping-pong&quot; aria-label=&quot;Anchor link for: porcupine-pigeons-playing-ping-pong&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8YgfgRaKwU0&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;8YgfgRaKwU0&#x2F;0.jpg&quot; alt=&quot;Porcupine&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;misirlou-ashar-kazi-shruti-naik-cover&quot;&gt;Misirlou - Ashar Kazi &amp;amp; Shruti Naik (cover)&lt;a class=&quot;zola-anchor&quot; href=&quot;#misirlou-ashar-kazi-shruti-naik-cover&quot; aria-label=&quot;Anchor link for: misirlou-ashar-kazi-shruti-naik-cover&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=HFozPnOI6zk&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;HFozPnOI6zk&#x2F;0.jpg&quot; alt=&quot;Misirlou&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;redbone-childish-gambino-ukulele-cover&quot;&gt;Redbone - Childish Gambino (ukulele cover)&lt;a class=&quot;zola-anchor&quot; href=&quot;#redbone-childish-gambino-ukulele-cover&quot; aria-label=&quot;Anchor link for: redbone-childish-gambino-ukulele-cover&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=dBf8wqlXx3c&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;dBf8wqlXx3c&#x2F;0.jpg&quot; alt=&quot;Redbone&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Do reach out to me &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&quot;&gt;@mrkaran_&lt;&#x2F;a&gt; with your dose of music reccos.&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Receiving notifications from Supervisor</title>
        <published>2018-06-03T10:57:55+05:30</published>
        <updated>2018-06-03T10:57:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/supervisor-notifications/"/>
        <id>https://mrkaran.dev/posts/supervisor-notifications/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/supervisor-notifications/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;supervisor-notifications&#x2F;images&#x2F;supervisor-zine.jpg&quot; alt=&quot;Supervisor Events Zine&quot; title=&quot;Supervisor Events Zine&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;supervisor-events&quot;&gt;Supervisor Events&lt;a class=&quot;zola-anchor&quot; href=&quot;#supervisor-events&quot; aria-label=&quot;Anchor link for: supervisor-events&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I had a seemingly simple task which was to receive notifications any time a process managed by Supervisor restarts. I wanted a generic solution where I could get notifications for any change in the process state. &lt;code&gt;Supervisor Events&lt;&#x2F;code&gt; saved my day, although I would admit it wasn’t straightforward to set up.&lt;&#x2F;p&gt;
&lt;p&gt;Supervisor uses &lt;code&gt;STDIN&#x2F;STDOUT&lt;&#x2F;code&gt; mechanism to communicate with the event listener. You need to configure your event listener in such a way that it can understand the &lt;code&gt;STDIN&lt;&#x2F;code&gt; sent by Supervisor and also communicate back using &lt;code&gt;STDOUT&lt;&#x2F;code&gt;. You can write this event handler in any language you like as long as you conform to the specially formatted messages that Supervisor sends and expects. I had struggled the most at this step and my &lt;code&gt;google-fu&lt;&#x2F;code&gt; didn’t help much in this case.&lt;&#x2F;p&gt;
&lt;p&gt;Supervisor by default will send these events even if no listener is configured. Once you have your own listener setup, you can execute any task you want, eg: send email&#x2F;telegram&#x2F;slack messages etc.&lt;&#x2F;p&gt;
&lt;p&gt;In order to configure your event listener, you need to add it to your &lt;code&gt;supervisor.conf&lt;&#x2F;code&gt;. Here’s an example configuration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;eventlistener:wowevent&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;command&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;events&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;G&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;process_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;program_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;process_num&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;numprocs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autorestart&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stderr_logfile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stdout_logfile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the program to know that it has to send a notification at &lt;code&gt;wowevent&lt;&#x2F;code&gt; pool, you need to add the &lt;code&gt;events&lt;&#x2F;code&gt; key to the &lt;code&gt;program&lt;&#x2F;code&gt; section of &lt;code&gt;supervisor.conf&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;program:myprog&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;events&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;O&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;G&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now everytime &lt;code&gt;myprog&lt;&#x2F;code&gt; is about to start, it will send an event to &lt;code&gt;wowevent&lt;&#x2F;code&gt; event pool. Your event listener which is configured at &lt;code&gt;&#x2F;home&#x2F;work&#x2F;testevent&#x2F;test.py&lt;&#x2F;code&gt; will handle the notification and execute tasks which you want to perform.&lt;&#x2F;p&gt;
&lt;p&gt;There are a bunch of event states that Supervisor captures, I was interested in knowing when my process has started, so I used &lt;code&gt;PROCESS_STATE_RUNNING&lt;&#x2F;code&gt;. You can take a look at all different event types &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;supervisord.org&#x2F;events.html#event-types&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;During all this experimentation I came across a bug (which I later found it is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Supervisor&#x2F;supervisor&#x2F;issues&#x2F;339&quot;&gt;known issue&lt;&#x2F;a&gt;, and an open bug since 4 years now). If you’ve been using Supervisor I am sure at least once you’ve been bitten by not &lt;code&gt;rereading&lt;&#x2F;code&gt; the config file and wondering why Supervisor isn’t picking up changes in config file when you restart the Supervisor. So &lt;code&gt;reread&lt;&#x2F;code&gt; and &lt;code&gt;update&lt;&#x2F;code&gt; becomes a muscle memory after this event &lt;i class=&quot;em em-stuck_out_tongue_closed_eyes&quot;&gt;&lt;&#x2F;i&gt;.
The bug with events is that if you make any changes to the event group, &lt;code&gt;reread&lt;&#x2F;code&gt; doesn’t pick up this change. I initially thought this must be the standard way Supervisor is behaving because I didn’t change any &lt;code&gt;program&lt;&#x2F;code&gt; group. I randomly decided to change the event listener name and BAM! Supervisor read the new configuration and everything suddenly works! ARGH. Why do complex problems have such simple solutions &lt;i class=&quot;em em-smiley&quot;&gt;&lt;&#x2F;i&gt; (not a solution, rather a workaround, but you get the drift right?)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;supervisor-event-listener-protocol&quot;&gt;Supervisor Event Listener Protocol&lt;a class=&quot;zola-anchor&quot; href=&quot;#supervisor-event-listener-protocol&quot; aria-label=&quot;Anchor link for: supervisor-event-listener-protocol&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Supervisor sends a header which is a key value pair of meta-attributes about the process and event. This header looks something like&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;ver:3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; server:supervisor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; serial:208&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pool:mylistener&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; poolserial:0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eventname:PROCESS_STATE_RUNNING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; len:69&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The event listener &lt;code&gt;mylistener&lt;&#x2F;code&gt; will be in &lt;code&gt;ACKNOWLEDGED&lt;&#x2F;code&gt; state when Supervisor sends the event &lt;code&gt;PROCESS_STATE_RUNNING&lt;&#x2F;code&gt;. Now that the &lt;code&gt;myslistener&lt;&#x2F;code&gt; state has received this &lt;code&gt;ACKNOWLEDGED&lt;&#x2F;code&gt; state, the event listener will send &lt;code&gt;READY&lt;&#x2F;code&gt; back to Supervisor. This is to let Supervisor know that the listener has received the notification.
Supervisor puts the listener to &lt;code&gt;BUSY&lt;&#x2F;code&gt; state now and here you can do write your custom task. Supervisor waits for the task to get executed and when it does, the listener needs to communicate back with the result. This process is one full request-response cycle.&lt;&#x2F;p&gt;
&lt;p&gt;Let us write a simple Python script which will listen to Supervisor event notification and communicate back, all in a protocol Supervisor understands.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; sys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; requests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; logging&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; logging&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getLogger&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;event_listener&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;handler&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; logging&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;FileHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&#x2F;home&#x2F;user&#x2F;prod&#x2F;events&#x2F;logs&#x2F;response.log&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;formatter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; logging&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Formatter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;%(asctime)s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; %(levelname)s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt; %(message)s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;handler&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;setFormatter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;formatter&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logger&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;addHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;handler&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logger&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;setLevel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;logging&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;DEBUG&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here I am just setting up basic logging structure since I want to keep the &lt;code&gt;stdout&lt;&#x2F;code&gt; messages separate from what Supervisor uses.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; write_stdout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; only eventlistener protocol messages may be sent to stdout&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sys&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stdout&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sys&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stdout&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;flush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; write_stderr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sys&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stderr&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sys&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stderr&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;flush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have written helper functions which will be used to communicate with Supervisor. Now comes the &lt;code&gt;main&lt;&#x2F;code&gt; part (Sorry for bad pun! &lt;i class=&quot;em em-blush&quot;&gt;&lt;&#x2F;i&gt;)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #DCBDFB);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Hey Supervisor, I&amp;#39;m ready for some action&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        write_stdout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;READY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; Reading the header from STDIN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sys&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stdin&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;readline&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        write_stderr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;line&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; read event payload and print it to stderr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        headers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; dict&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sys&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stdin&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;headers&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        write_stderr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; add your events here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        notify_user&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #768390);&quot;&gt; transition from READY to ACKNOWLEDGED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        write_stdout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;RESULT 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;OK&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        logger&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;debug&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;It&amp;#39;s all fine and dandy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #6CB6FF);&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F47067);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let us break this into pieces.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;write_stdout(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;READY\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We flush &lt;code&gt;READY&lt;&#x2F;code&gt; with a linefeed character (&lt;code&gt;\n&lt;&#x2F;code&gt;) to &lt;code&gt;STDOUT&lt;&#x2F;code&gt;. Supervisor has put mylistener to &lt;code&gt;BUSY&lt;&#x2F;code&gt; state now.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sys.stdin.readline&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;write_stderr(line&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;line&lt;&#x2F;code&gt; would be the header which we discussed previously.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; sys.stdin.read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;int(headers[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This part is interesting. Here, we capture the &lt;code&gt;len&lt;&#x2F;code&gt; key from the header and read the next &lt;code&gt;STDIN&lt;&#x2F;code&gt; line up to this many chars. The &lt;code&gt;data&lt;&#x2F;code&gt; would consist of our event payload.
Event payload looks something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #F69D50);&quot;&gt;processname:prog-restartv3_0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; groupname:prog-restartv3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; from_state:STOPPED&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; tries:0ver:3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; server:supervisor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; serial:25&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; pool:prog-restartv3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; poolserial:3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; eventname:PROCESS_STATE_STARTING&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt; len:76&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;notify_user&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the handler where you can send an email, send a request to API, log it to file etc.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #ADBAC7); background-color: light-dark(#FFFFFF, #22272E);&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;write_stdout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;RESULT 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #F47067);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;OK&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #96D0FF);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, we tell Supervisor to put the listener from &lt;code&gt;BUSY&lt;&#x2F;code&gt; to &lt;code&gt;ACKNOWLEDGED&lt;&#x2F;code&gt; state, by sending a result structure. The result could be &lt;code&gt;FAIL&lt;&#x2F;code&gt; or &lt;code&gt;OK&lt;&#x2F;code&gt;, so you need to send &lt;code&gt;RESULT&lt;&#x2F;code&gt; followed by the length of the state variable. For example for &lt;code&gt;OK&lt;&#x2F;code&gt; you will send &lt;code&gt;RESULT 2\nOK&lt;&#x2F;code&gt; but for &lt;code&gt;FAIL&lt;&#x2F;code&gt; you have to send &lt;code&gt;RESULT 4\nFAIL&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That’s pretty much all you need to start receiving notifications from Supervisor every time your program changes its state. If you found this article useful, I’d love if you share this on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;intent&#x2F;tweet?url=https%3A%2F%2Fmr-karan.github.io%2Fposts%2Fsupervisor-notifications&amp;amp;text=Receiving%20notifications%20from%20Supervisor&quot;&gt;Twitter&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.facebook.com&#x2F;sharer&#x2F;sharer.php?u=https%3A%2F%2Fmr-karan.github.io%2Fposts%2Fsupervisor-notifications&quot;&gt;Facebook&lt;&#x2F;a&gt; and let your friends know about it too.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bi-Weekly Music Post Part 1</title>
        <published>2018-05-28T20:30:55+05:30</published>
        <updated>2018-05-28T20:30:55+05:30</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://mrkaran.dev/posts/biweekly-music-part-1/"/>
        <id>https://mrkaran.dev/posts/biweekly-music-part-1/</id>
        
        <content type="html" xml:base="https://mrkaran.dev/posts/biweekly-music-part-1/">&lt;p&gt;I listen to a &lt;em&gt;lot&lt;&#x2F;em&gt; of music artists while working or otherwise. I plan to share some of the gems I discover each week. Thanks to Spotify and Youtube suggestions, I keep discovering a lot of indie artists and underrated titles. I hope you give them a listen and spread some good music in your circle.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tere-jeya-hor-disda&quot;&gt;Tere Jeya Hor Disda&lt;a class=&quot;zola-anchor&quot; href=&quot;#tere-jeya-hor-disda&quot; aria-label=&quot;Anchor link for: tere-jeya-hor-disda&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=d_gZTh-HrZE&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;d_gZTh-HrZE&#x2F;0.jpg&quot; alt=&quot;Tere Jeya Hor Disda&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;awari&quot;&gt;Awari&lt;a class=&quot;zola-anchor&quot; href=&quot;#awari&quot; aria-label=&quot;Anchor link for: awari&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=dPAqQI_kOng&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;dPAqQI_kOng&#x2F;0.jpg&quot; alt=&quot;Awari&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;magpie-jay-bigfoot&quot;&gt;Magpie Jay - Bigfoot&lt;a class=&quot;zola-anchor&quot; href=&quot;#magpie-jay-bigfoot&quot; aria-label=&quot;Anchor link for: magpie-jay-bigfoot&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=kXCPLYeDXSI&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;kXCPLYeDXSI&#x2F;0.jpg&quot; alt=&quot;Magpie Jay - Bigfoot&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-local-train-dilnawaz&quot;&gt;The Local Train - Dilnawaz&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-local-train-dilnawaz&quot; aria-label=&quot;Anchor link for: the-local-train-dilnawaz&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=-gKBXwXBUbk&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;-gKBXwXBUbk&#x2F;0.jpg&quot; alt=&quot;The Local Train - Dilnawaz&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-ha-take-on-me&quot;&gt;a-ha - Take On Me&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-ha-take-on-me&quot; aria-label=&quot;Anchor link for: a-ha-take-on-me&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=djV11Xbc914&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;djV11Xbc914&#x2F;0.jpg&quot; alt=&quot;a-ha - Take On Me&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lord-huron-the-night-we-met&quot;&gt;Lord Huron - The Night We Met&lt;a class=&quot;zola-anchor&quot; href=&quot;#lord-huron-the-night-we-met&quot; aria-label=&quot;Anchor link for: lord-huron-the-night-we-met&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=KtlgYxa6BMU&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;KtlgYxa6BMU&#x2F;0.jpg&quot; alt=&quot;Lord Huron - The Night We Met&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;snowmine-let-me-in&quot;&gt;Snowmine - Let me in&lt;a class=&quot;zola-anchor&quot; href=&quot;#snowmine-let-me-in&quot; aria-label=&quot;Anchor link for: snowmine-let-me-in&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=_y3GfgcgB_E&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;_y3GfgcgB_E&#x2F;0.jpg&quot; alt=&quot;Snowmine - Let me in&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;glass-animals-pork-soda&quot;&gt;Glass Animals - Pork Soda&lt;a class=&quot;zola-anchor&quot; href=&quot;#glass-animals-pork-soda&quot; aria-label=&quot;Anchor link for: glass-animals-pork-soda&quot;&gt;#&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=78DVtcsT26k&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.youtube.com&#x2F;vi&#x2F;78DVtcsT26k&#x2F;0.jpg&quot; alt=&quot;Glass Animals - Pork Soda&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you liked the above recommendations or you want to share moar music which I should definitely listen to, tweet to me &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mrkaran_&quot;&gt;@mrkaran_&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fin!&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
